diff --git a/.changeset/afraid-houses-learn.md b/.changeset/afraid-houses-learn.md new file mode 100644 index 00000000000..3d161965bae --- /dev/null +++ b/.changeset/afraid-houses-learn.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#updated use real contracts in ccipreader_tests where possible diff --git a/.changeset/breezy-kings-clean.md b/.changeset/breezy-kings-clean.md new file mode 100644 index 00000000000..b72a0689019 --- /dev/null +++ b/.changeset/breezy-kings-clean.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Potential bug introduced from chain selector refactor, not causing issue now since only EVM is used, but need to fix #bugfix diff --git a/.changeset/clean-files-beg.md b/.changeset/clean-files-beg.md new file mode 100644 index 00000000000..1357a044cb0 --- /dev/null +++ b/.changeset/clean-files-beg.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Adding OCR3 promwrapper to LLO #internal diff --git a/.changeset/cool-penguins-raise.md b/.changeset/cool-penguins-raise.md new file mode 100644 index 00000000000..c47839be310 --- /dev/null +++ b/.changeset/cool-penguins-raise.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#updated Remove custom ed25519 private to public key conversion. diff --git a/.changeset/dull-readers-rush.md b/.changeset/dull-readers-rush.md new file mode 100644 index 00000000000..3b6f2ae8758 --- /dev/null +++ b/.changeset/dull-readers-rush.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Reporting number of OCR3 instances running using promwrapper #internal diff --git a/.changeset/fuzzy-hairs-appear.md b/.changeset/fuzzy-hairs-appear.md new file mode 100644 index 00000000000..a4797462546 --- /dev/null +++ b/.changeset/fuzzy-hairs-appear.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Prometheus observability layer added to OCR3 Reporting Plugins #internal diff --git a/.changeset/hot-islands-dress.md b/.changeset/hot-islands-dress.md new file mode 100644 index 00000000000..82e34ecf42b --- /dev/null +++ b/.changeset/hot-islands-dress.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal refactor: inject ocr secrets via env instead of config diff --git a/.changeset/late-doors-battle.md b/.changeset/late-doors-battle.md new file mode 100644 index 00000000000..8ec64b9048e --- /dev/null +++ b/.changeset/late-doors-battle.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Fix TransactionSender go routine leak. #bugfix diff --git a/.changeset/spotty-knives-smile.md b/.changeset/spotty-knives-smile.md new file mode 100644 index 00000000000..8389b72414c --- /dev/null +++ b/.changeset/spotty-knives-smile.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Increase GasLimit for Automation on ZKsync to 6M #nops diff --git a/.changeset/thin-cats-try.md b/.changeset/thin-cats-try.md new file mode 100644 index 00000000000..e7934fe279a --- /dev/null +++ b/.changeset/thin-cats-try.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Add support for Mercury LLO streams to feeds service. #added diff --git a/.changeset/tricky-clouds-move.md b/.changeset/tricky-clouds-move.md new file mode 100644 index 00000000000..8cb50dbb048 --- /dev/null +++ b/.changeset/tricky-clouds-move.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Updated Solana TXM to store prebroadcast transaction errors caught upfront by simulation. Refactored error parsing to more easily introduce new error cases. Optimized storing finalized and errored transaction to minimize memory usage. #updated diff --git a/.changeset/wet-bags-clean.md b/.changeset/wet-bags-clean.md new file mode 100644 index 00000000000..53da05426c9 --- /dev/null +++ b/.changeset/wet-bags-clean.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Change ChainWriter naming to ContractWriter to consolidate Relayer chain interfaces #internal diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 210709443be..c2d6208d0e3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -133,14 +133,13 @@ core/scripts/gateway @smartcontractkit/dev-services # Tests /integration-tests/ @smartcontractkit/test-tooling-team @smartcontractkit/core -/integration-tests/ccip-tests @smartcontractkit/ccip-offchain @smartcontractkit/core +/integration-tests/ccip-tests @smartcontractkit/ccip-offchain @smartcontractkit/core @smartcontractkit/ccip /integration-tests/**/*keeper* @smartcontractkit/dev-services @smartcontractkit/core /integration-tests/**/*automation* @smartcontractkit/dev-services @smartcontractkit/core -/integration-tests/**/*ccip* @smartcontractkit/ccip-offchain @smartcontractkit/core +/integration-tests/**/*ccip* @smartcontractkit/ccip-offchain @smartcontractkit/core @smartcontractkit/ccip # Deployment tooling -# Initially the common structures owned by CCIP -/deployment @smartcontractkit/ccip @smartcontractkit/keystone @smartcontractkit/core +/deployment @smartcontractkit/ccip @smartcontractkit/keystone @smartcontractkit/core @smartcontractkit/deployment-automation /deployment/ccip @smartcontractkit/ccip @smartcontractkit/core /deployment/keystone @smartcontractkit/keystone @smartcontractkit/core # TODO: As more products add their deployment logic here, add the team as an owner diff --git a/.github/actions/version-file-bump/action.yml b/.github/actions/version-file-bump/action.yml index eb8d5c17426..17bdc71a716 100644 --- a/.github/actions/version-file-bump/action.yml +++ b/.github/actions/version-file-bump/action.yml @@ -1,5 +1,5 @@ name: version-file-bump -description: "Ensure that the VERSION file has been bumped since the last release." +description: "Ensure that the package.json version field has been bumped since the last release." inputs: github-token: description: "Github access token" diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml index 9f6495c46f7..d40d375f860 100644 --- a/.github/e2e-tests.yml +++ b/.github/e2e-tests.yml @@ -942,46 +942,46 @@ runner-test-matrix: triggers: - PR E2E Core Tests - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test ccip_test.go -timeout 12m -test.parallel=2 -count=1 -json + test_cmd: cd integration-tests/smoke/ccip && go test ccip_test.go -timeout 25m -test.parallel=2 -count=1 -json pyroscope_env: ci-smoke-ccipv1_6-evm-simulated test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - - - id: smoke/ccip/ccip_batching_test.go:* - path: integration-tests/smoke/ccip/ccip_batching_test.go + + - id: smoke/ccip/ccip_message_limitations_test.go:* + path: integration-tests/smoke/ccip/ccip_message_limitations_test.go test_env_type: docker runs_on: ubuntu-latest triggers: - PR E2E Core Tests - Nightly E2E Tests - test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_batching_test.go -timeout 12m -test.parallel=1 -count=1 -json + test_cmd: cd integration-tests/smoke/ccip && go test -run '^Test_CCIPMessageLimitations' -timeout 18m -test.parallel=1 -count=1 -json ./... pyroscope_env: ci-smoke-ccipv1_6-evm-simulated test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2,SIMULATED_3 + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - - id: smoke/ccip/ccip_usdc_test.go:* - path: integration-tests/smoke/ccip/ccip_usdc_test.go + - id: smoke/ccip/ccip_token_price_updates_test.go:* + path: integration-tests/smoke/ccip/ccip_token_price_updates_test.go test_env_type: docker runs_on: ubuntu-latest triggers: - PR E2E Core Tests - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test ccip_usdc_test.go -timeout 18m -test.parallel=1 -count=1 -json + test_cmd: cd integration-tests/smoke/ccip && go test ccip_token_price_updates_test.go -timeout 18m -test.parallel=1 -count=1 -json pyroscope_env: ci-smoke-ccipv1_6-evm-simulated test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2,SIMULATED_3 + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - - id: smoke/ccip/fee_boosting_test.go:* - path: integration-tests/smoke/ccip/fee_boosting_test.go + - id: smoke/ccip/ccip_gas_price_updates_test.go:* + path: integration-tests/smoke/ccip/ccip_gas_price_updates_test.go test_env_type: docker runs_on: ubuntu-latest triggers: - PR E2E Core Tests - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test fee_boosting_test.go -timeout 15m -test.parallel=1 -count=1 -json + test_cmd: cd integration-tests/smoke/ccip && go test ccip_gas_price_updates_test.go -timeout 18m -test.parallel=1 -count=1 -json pyroscope_env: ci-smoke-ccipv1_6-evm-simulated test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 @@ -1017,21 +1017,20 @@ runner-test-matrix: E2E_RMN_RAGEPROXY_VERSION: master-f461a9e E2E_RMN_AFN2PROXY_VERSION: master-f461a9e -# Enable after flaking issue is resolved -# - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_NotEnoughObservers$ -# path: integration-tests/smoke/ccip/ccip_rmn_test.go -# test_env_type: docker -# runs_on: ubuntu-latest -# triggers: -# - PR E2E Core Tests -# - Nightly E2E Tests -# test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_NotEnoughObservers$ -timeout 12m -test.parallel=1 -count=1 -json -# pyroscope_env: ci-smoke-ccipv1_6-evm-simulated -# test_env_vars: -# E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 -# E2E_JD_VERSION: 0.6.0 -# E2E_RMN_RAGEPROXY_VERSION: master-f461a9e -# E2E_RMN_AFN2PROXY_VERSION: master-f461a9e + - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_NotEnoughObservers$ + path: integration-tests/smoke/ccip/ccip_rmn_test.go + test_env_type: docker + runs_on: ubuntu-latest + triggers: + - PR E2E Core Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_NotEnoughObservers$ -timeout 12m -test.parallel=1 -count=1 -json + pyroscope_env: ci-smoke-ccipv1_6-evm-simulated + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + E2E_JD_VERSION: 0.6.0 + E2E_RMN_RAGEPROXY_VERSION: master-f461a9e + E2E_RMN_AFN2PROXY_VERSION: master-f461a9e - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_DifferentSigners$ path: integration-tests/smoke/ccip/ccip_rmn_test.go @@ -1048,22 +1047,20 @@ runner-test-matrix: E2E_RMN_RAGEPROXY_VERSION: master-f461a9e E2E_RMN_AFN2PROXY_VERSION: master-f461a9e -# Enable after flaking issue is resolved -# - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_NotEnoughSigners$ -# path: integration-tests/smoke/ccip/ccip_rmn_test.go -# test_env_type: docker -# runs_on: ubuntu-latest -# triggers: -# - PR E2E Core Tests -# - Nightly E2E Tests -# test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_NotEnoughSigners$ -timeout 12m -test.parallel=1 -count=1 -json -# pyroscope_env: ci-smoke-ccipv1_6-evm-simulated -# test_env_vars: -# E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 -# E2E_JD_VERSION: 0.6.0 -# E2E_RMN_RAGEPROXY_VERSION: master-f461a9e -# E2E_RMN_AFN2PROXY_VERSION: master-f461a9e - + - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_NotEnoughSigners$ + path: integration-tests/smoke/ccip/ccip_rmn_test.go + test_env_type: docker + runs_on: ubuntu-latest + triggers: + - PR E2E Core Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_NotEnoughSigners$ -timeout 12m -test.parallel=1 -count=1 -json + pyroscope_env: ci-smoke-ccipv1_6-evm-simulated + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + E2E_JD_VERSION: 0.6.0 + E2E_RMN_RAGEPROXY_VERSION: master-f461a9e + E2E_RMN_AFN2PROXY_VERSION: master-f461a9e - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_DifferentRmnNodesForDifferentChains$ path: integration-tests/smoke/ccip/ccip_rmn_test.go @@ -1080,6 +1077,35 @@ runner-test-matrix: E2E_RMN_RAGEPROXY_VERSION: master-f461a9e E2E_RMN_AFN2PROXY_VERSION: master-f461a9e + - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_TwoMessagesOneSourceChainCursed$ + path: integration-tests/smoke/ccip/ccip_rmn_test.go + test_env_type: docker + runs_on: ubuntu-latest + triggers: + - PR E2E Core Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_TwoMessagesOneSourceChainCursed$ -timeout 12m -test.parallel=1 -count=1 -json + pyroscope_env: ci-smoke-ccipv1_6-evm-simulated + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + E2E_JD_VERSION: 0.6.0 + E2E_RMN_RAGEPROXY_VERSION: master-f461a9e + E2E_RMN_AFN2PROXY_VERSION: master-f461a9e + + - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_GlobalCurseTwoMessagesOnTwoLanes$ + path: integration-tests/smoke/ccip/ccip_rmn_test.go + test_env_type: docker + runs_on: ubuntu-latest + triggers: + - PR E2E Core Tests + - Nightly E2E Tests + test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_GlobalCurseTwoMessagesOnTwoLanes$ -timeout 12m -test.parallel=1 -count=1 -json + pyroscope_env: ci-smoke-ccipv1_6-evm-simulated + test_env_vars: + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 + E2E_JD_VERSION: 0.6.0 + E2E_RMN_RAGEPROXY_VERSION: master-f461a9e + E2E_RMN_AFN2PROXY_VERSION: master-f461a9e # END: CCIPv1.6 tests diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index f97f3332eb7..b7522274d85 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -8,6 +8,14 @@ runner-test-matrix: # START: CCIPv1.6 tests + - id: smoke/ccip/ccip_fees_test.go:* + path: integration-tests/smoke/ccip/ccip_fees_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/smoke/ccip && go test ccip_fees_test.go -timeout 12m -test.parallel=2 -count=1 -json + - id: smoke/ccip/ccip_messaging_test.go:* path: integration-tests/smoke/ccip/ccip_messaging_test.go test_env_type: in-memory @@ -15,4 +23,53 @@ runner-test-matrix: triggers: - PR Integration CCIP Tests test_cmd: cd integration-tests/smoke/ccip && go test ccip_messaging_test.go -timeout 12m -test.parallel=2 -count=1 -json + + - id: smoke/ccip/ccip_fee_boosting_test.go:* + path: integration-tests/smoke/ccip/ccip_fee_boosting_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/smoke/ccip && go test ccip_fee_boosting_test.go -timeout 12m -test.parallel=2 -count=1 -json + + - id: smoke/ccip/ccip_batching_test.go:* + path: integration-tests/smoke/ccip/ccip_batching_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/smoke/ccip && go test ccip_batching_test.go -timeout 12m -test.parallel=2 -count=1 -json + + - id: contracts/ccipreader_test.go:* + path: integration-tests/contracts/ccipreader_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/contracts && go test ccipreader_test.go -timeout 5m -test.parallel=1 -count=1 -json + + - id: smoke/ccip/ccip_usdc_test.go:* + path: integration-tests/smoke/ccip/ccip_usdc_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/smoke/ccip && go test ccip_usdc_test.go -timeout 18m -test.parallel=1 -count=1 -json + + - id: smoke/ccip/ccip_ooo_execution_test.go:* + path: integration-tests/smoke/ccip/ccip_ooo_execution_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_ooo_execution_test.go -timeout 16m -test.parallel=1 -count=1 -json + + - id: smoke/ccip/ccip_token_transfer_test.go:* + path: integration-tests/smoke/ccip/ccip_token_transfer_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_token_transfer_test.go -timeout 16m -test.parallel=1 -count=1 -json + # END: CCIP tests diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml index 9a4a127dede..3a826f523a0 100644 --- a/.github/workflows/automation-benchmark-tests.yml +++ b/.github/workflows/automation-benchmark-tests.yml @@ -20,17 +20,22 @@ on: required: true default: benchmark type: string + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + type: string jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: test_path: .github/e2e-tests.yml test_ids: '${{ inputs.testType }}/automation_test.go:TestAutomationBenchmark' test_config_override_path: ${{ inputs.test_config_override_path }} SLACK_USER: ${{ inputs.slackMemberID }} SLACK_CHANNEL: C03KJ5S7KEK + team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/automation-load-tests.yml b/.github/workflows/automation-load-tests.yml index 24c7017ee9a..c11e353a7db 100644 --- a/.github/workflows/automation-load-tests.yml +++ b/.github/workflows/automation-load-tests.yml @@ -14,18 +14,23 @@ on: description: Notifies test results (Not your @) required: true default: U02Q14G80TY - type: string + type: string + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + type: string jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: test_path: .github/e2e-tests.yml test_ids: 'load/automationv2_1/automationv2_1_test.go:TestLogTrigger' test_config_override_path: ${{ inputs.test_config_override_path }} SLACK_USER: ${{ inputs.slackMemberID }} SLACK_CHANNEL: C03KJ5S7KEK + team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml index c72715bf9db..eef02dcddb2 100644 --- a/.github/workflows/automation-ondemand-tests.yml +++ b/.github/workflows/automation-ondemand-tests.yml @@ -38,7 +38,11 @@ on: with_existing_remote_runner_version: description: 'Tag of the existing remote runner version to use (Leave empty to build from head/ref)' required: false - type: string + type: string + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + type: string jobs: # Set tests to run based on the workflow inputs @@ -153,7 +157,7 @@ jobs: call-run-e2e-tests-workflow: name: Run E2E Tests needs: set-tests-to-run - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: test_path: .github/e2e-tests.yml test_list: ${{ needs.set-tests-to-run.outputs.test_list }} @@ -161,6 +165,7 @@ jobs: with_existing_remote_runner_version: ${{ github.event.inputs.with_existing_remote_runner_version }} test_log_upload_on_failure: true test_log_upload_retention_days: 7 + team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/build-publish-develop-pr.yml b/.github/workflows/build-publish-develop-pr.yml index 68075422adf..92d9e0445a6 100644 --- a/.github/workflows/build-publish-develop-pr.yml +++ b/.github/workflows/build-publish-develop-pr.yml @@ -2,9 +2,9 @@ name: "Build and Publish GoReleaser" on: pull_request: - # The default types are opened, synchronize, and reopened - # See https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request - # We add a label trigger too, since when the build-publish label is added to a PR, we want to build and publish + # The default types are opened, synchronize, and reopened + # See https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request + # We add a label trigger too, since when the build-publish label is added to a PR, we want to build and publish types: - opened - synchronize @@ -28,49 +28,41 @@ env: # a commit is pushed to develop before merge is run. CHECKOUT_REF: ${{ github.event.inputs.git_ref || github.sha }} - jobs: - merge: + image-tag: runs-on: ubuntu-latest - needs: [split, image-tag] - if: ${{ needs.image-tag.outputs.release-type == 'nightly' }} - permissions: - id-token: write - contents: read + outputs: + image-tag: ${{ steps.get-image-tag.outputs.image-tag }} + release-type: ${{ steps.get-image-tag.outputs.release-type }} steps: - name: Checkout repository uses: actions/checkout@v4.2.1 with: ref: ${{ env.CHECKOUT_REF }} - - name: Configure aws credentials - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 - with: - role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_BUILD_PUBLISH_DEVELOP_PR }} - aws-region: ${{ secrets.AWS_REGION }} - mask-aws-account-id: true - role-session-name: "merge" - - - uses: actions/cache/restore@v4.1.1 - with: - path: dist/linux_amd64_v1 - key: chainlink-amd64-${{ github.sha }} - fail-on-cache-miss: true - - - uses: actions/cache/restore@v4.1.1 - with: - path: dist/linux_arm64_v8.0 - key: chainlink-arm64-${{ github.sha }} - fail-on-cache-miss: true - - - name: Merge images for both architectures - uses: ./.github/actions/goreleaser-build-sign-publish - with: - docker-registry: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }} - docker-image-tag: ${{ needs.image-tag.outputs.image-tag }} - goreleaser-release-type: "merge" - goreleaser-config: .goreleaser.develop.yaml - goreleaser-key: ${{ secrets.GORELEASER_KEY }} + - name: Get image tag + id: get-image-tag + run: | + short_sha=$(git rev-parse --short HEAD) + echo "release-type=snapshot" | tee -a $GITHUB_OUTPUT + if [[ ${{ github.event_name }} == 'push' ]]; then + echo "image-tag=develop" | tee -a $GITHUB_OUTPUT + echo "release-type=nightly" | tee -a $GITHUB_OUTPUT + elif [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then + echo "image-tag=${short_sha}" | tee -a $GITHUB_OUTPUT + if [[ "${{ inputs.build-publish }}" == 'false' ]]; then + echo "release-type=snapshot" | tee -a $GITHUB_OUTPUT + else + echo "release-type=nightly" | tee -a $GITHUB_OUTPUT + fi + else + if [[ ${{ github.event_name }} == "pull_request" ]]; then + echo "image-tag=pr-${{ github.event.number }}-${short_sha}" | tee -a $GITHUB_OUTPUT + if [[ ${{ contains(github.event.pull_request.labels.*.name, 'build-publish') }} == "true" ]]; then + echo "release-type=nightly" | tee -a $GITHUB_OUTPUT + fi + fi + fi split: name: "split-${{ matrix.goarch }}" @@ -113,7 +105,7 @@ jobs: - name: Build images for ${{ matrix.goarch }} uses: ./.github/actions/goreleaser-build-sign-publish - if: steps.cache.outputs.cache-hit != 'true' + if: github.event_name == 'workflow_dispatch' || steps.cache.outputs.cache-hit != 'true' with: docker-registry: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }} docker-image-tag: ${{ needs.image-tag.outputs.image-tag }} @@ -121,37 +113,44 @@ jobs: goreleaser-config: .goreleaser.develop.yaml goreleaser-key: ${{ secrets.GORELEASER_KEY }} - image-tag: + merge: runs-on: ubuntu-latest - outputs: - image-tag: ${{ steps.get-image-tag.outputs.image-tag }} - release-type: ${{ steps.get-image-tag.outputs.release-type }} + needs: [split, image-tag] + if: ${{ needs.image-tag.outputs.release-type == 'nightly' }} + permissions: + id-token: write + contents: read steps: - name: Checkout repository uses: actions/checkout@v4.2.1 with: ref: ${{ env.CHECKOUT_REF }} - - name: Get image tag - id: get-image-tag - run: | - short_sha=$(git rev-parse --short HEAD) - echo "release-type=snapshot" | tee -a $GITHUB_OUTPUT - if [[ ${{ github.event_name }} == 'push' ]]; then - echo "image-tag=develop" | tee -a $GITHUB_OUTPUT - echo "release-type=nightly" | tee -a $GITHUB_OUTPUT - elif [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then - echo "image-tag=${short_sha}" | tee -a $GITHUB_OUTPUT - if [[ "${{ inputs.build-publish }}" == 'false' ]]; then - echo "release-type=snapshot" | tee -a $GITHUB_OUTPUT - else - echo "release-type=nightly" | tee -a $GITHUB_OUTPUT - fi - else - if [[ ${{ github.event_name }} == "pull_request" ]]; then - echo "image-tag=pr-${{ github.event.number }}-${short_sha}" | tee -a $GITHUB_OUTPUT - if [[ ${{ contains(github.event.pull_request.labels.*.name, 'build-publish') }} == "true" ]]; then - echo "release-type=nightly" | tee -a $GITHUB_OUTPUT - fi - fi - fi + - name: Configure aws credentials + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_BUILD_PUBLISH_DEVELOP_PR }} + aws-region: ${{ secrets.AWS_REGION }} + mask-aws-account-id: true + role-session-name: "merge" + + - uses: actions/cache/restore@v4.1.1 + with: + path: dist/linux_amd64_v1 + key: chainlink-amd64-${{ github.sha }} + fail-on-cache-miss: true + + - uses: actions/cache/restore@v4.1.1 + with: + path: dist/linux_arm64_v8.0 + key: chainlink-arm64-${{ github.sha }} + fail-on-cache-miss: true + + - name: Merge images for both architectures + uses: ./.github/actions/goreleaser-build-sign-publish + with: + docker-registry: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }} + docker-image-tag: ${{ needs.image-tag.outputs.image-tag }} + goreleaser-release-type: "merge" + goreleaser-config: .goreleaser.develop.yaml + goreleaser-key: ${{ secrets.GORELEASER_KEY }} diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml index 3d7e925dba0..2889ee5e5ea 100644 --- a/.github/workflows/build-publish.yml +++ b/.github/workflows/build-publish.yml @@ -7,18 +7,48 @@ on: env: ECR_HOSTNAME: public.ecr.aws - ECR_IMAGE_NAME: chainlink/chainlink jobs: checks: name: "Checks" runs-on: ubuntu-20.04 + outputs: + git-tag-type: ${{ steps.check-git-tag-type.outputs.git-tag-type }} + ecr-image-name: ${{ steps.check-git-tag-type.outputs.ecr-image-name }} steps: - name: Checkout repository uses: actions/checkout@v4.2.1 + - name: Check git tag type + id: check-git-tag-type + shell: bash + env: + GIT_TAG: ${{ github.ref_name}} + run: | + # Check if git tag is related to CCIP + # Should match: + # v1.0.0-ccip1.0.0-beta.1 + # v1.0.0-ccip1.0.0-rc.0 + # v1.0.0-ccip1.0.0 + if [[ $GIT_TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+-ccip[0-9]+\.[0-9]+\.[0-9]+(-((beta|rc)\.[0-9]+))?$ ]]; then + echo "git-tag-type=ccip" | tee -a "$GITHUB_OUTPUT" + echo "ecr-image-name=chainlink/ccip" | tee -a "$GITHUB_OUTPUT" + else + echo "git-tag-type=core" | tee -a "$GITHUB_OUTPUT" + echo "ecr-image-name=chainlink/chainlink" | tee -a "$GITHUB_OUTPUT" + fi + - name: Fail if CCIP release has wrong version + if: ${{ steps.check-git-tag-type.outputs.git-tag-type == 'ccip' }} + run: | + version=$(jq -r '.version' ./package.json) + echo "Package version: $version" + echo "Git tag type: ${{ steps.check-git-tag-type.outputs.git-tag-type }}" + if [[ $version != *"-ccip"* ]]; then + echo "Error: Version '$version' does not match required CCIP format." + exit 1 + fi - name: Check for VERSION file bump on tags - # Avoids checking VERSION file bump on forks. - if: ${{ github.repository == 'smartcontractkit/chainlink' }} + # Avoids checking VERSION file bump on forks or from CCIP releases. + if: ${{ github.repository == 'smartcontractkit/chainlink' && steps.check-git-tag-type.outputs.git-tag-type == 'core' }} uses: ./.github/actions/version-file-bump with: github-token: ${{ secrets.GITHUB_TOKEN }} @@ -47,7 +77,7 @@ jobs: aws-role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }} aws-region: ${{ secrets.AWS_REGION }} ecr-hostname: ${{ env.ECR_HOSTNAME }} - ecr-image-name: ${{ env.ECR_IMAGE_NAME }} + ecr-image-name: ${{ needs.checks.outputs.ecr-image-name }} dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} sign-images: true @@ -57,13 +87,13 @@ jobs: uses: actions/attest-build-provenance@6149ea5740be74af77f260b9db67e633f6b0a9a1 # v1.4.2 with: subject-digest: ${{ steps.build-sign-publish.outputs.docker-image-digest }} - subject-name: ${{ env.ECR_HOSTNAME }}/${{ env.ECR_IMAGE_NAME }} + subject-name: ${{ env.ECR_HOSTNAME }}/${{ needs.checks.outputs.ecr-image-name }} push-to-registry: true # Notify Slack channel for new git tags. slack-notify: if: github.ref_type == 'tag' - needs: [build-sign-publish-chainlink] + needs: [checks, build-sign-publish-chainlink] runs-on: ubuntu-24.04 environment: build-publish steps: @@ -91,7 +121,7 @@ jobs: format( '{0}/{1}:{2}', env.ECR_HOSTNAME, - env.ECR_IMAGE_NAME, + needs.checks.outputs.ecr-image-name, needs.build-sign-publish-chainlink.outputs.docker-image-tag ) || '' }} diff --git a/.github/workflows/ccip-chaos-tests.yml b/.github/workflows/ccip-chaos-tests.yml index 36c99410c37..51e6c6f027a 100644 --- a/.github/workflows/ccip-chaos-tests.yml +++ b/.github/workflows/ccip-chaos-tests.yml @@ -6,6 +6,12 @@ on: # types: [ completed ] # branches: [ develop ] workflow_dispatch: + inputs: + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + default: "ccip" + type: string # Only run 1 of this workflow at a time per PR concurrency: @@ -15,7 +21,7 @@ concurrency: jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: test_path: .github/e2e-tests.yml chainlink_version: ${{ github.sha }} @@ -25,6 +31,7 @@ jobs: slack_notification_after_tests: on_failure slack_notification_after_tests_channel_id: '#ccip-testing' slack_notification_after_tests_name: CCIP Chaos E2E Tests + team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/ccip-load-tests.yml b/.github/workflows/ccip-load-tests.yml index 4f5b7ac509c..d1733147443 100644 --- a/.github/workflows/ccip-load-tests.yml +++ b/.github/workflows/ccip-load-tests.yml @@ -21,7 +21,12 @@ on: chainlink_version: description: Chainlink image version to use. Commit sha if not provided required: false - type: string + type: string + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + default: "ccip" + type: string # Only run 1 of this workflow at a time per PR concurrency: @@ -31,7 +36,7 @@ concurrency: jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: test_path: .github/e2e-tests.yml test_trigger: E2E CCIP Load Tests @@ -41,6 +46,7 @@ jobs: slack_notification_after_tests_channel_id: '#ccip-testing' slack_notification_after_tests_name: CCIP E2E Load Tests test_image_suites: ccip-load + team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/changeset.yml b/.github/workflows/changeset.yml index 19d17ddb588..d6d269326c7 100644 --- a/.github/workflows/changeset.yml +++ b/.github/workflows/changeset.yml @@ -162,3 +162,48 @@ jobs: run: | echo "Please include at least one tag in the core changeset file" exit 1 + + contracts-changeset: + name: Contracts Changeset Checker + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4.2.1 + with: + fetch-depth: 0 + + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: files-changed + with: + predicate-quantifier: every + list-files: shell + filters: | + contracts-changeset: + - added|modified: 'contracts/.changeset/*.md' + + - name: Setup node + uses: ./.github/actions/setup-nodejs + if: ${{ steps.files-changed.outputs.contracts-changeset == 'true' }} + + - name: Install base dependencies + if: ${{ steps.files-changed.outputs.contracts-changeset == 'true' }} + run: pnpm i + + - name: Validate changeset files + if: ${{ steps.files-changed.outputs.contracts-changeset == 'true' }} + working-directory: contracts + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + pnpm changeset version + + - name: Comment Failure + if: ${{ failure() && steps.files-changed.outputs.contracts-changeset == 'true' }} + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + message: | + It appears that the changeset file you've added or modified in `contracts/.changeset` is not valid. + Please delete the file and run `pnpm changeset` in the contracts directory. + diff --git a/.github/workflows/crib-integration-test.yml b/.github/workflows/crib-integration-test.yml index 5cd632dcecd..5dd24167ab0 100644 --- a/.github/workflows/crib-integration-test.yml +++ b/.github/workflows/crib-integration-test.yml @@ -76,7 +76,7 @@ jobs: echo $GITHUB_WORKSPACE - name: Deploy and validate CRIB Environment for Core - uses: smartcontractkit/.github/actions/crib-deploy-environment@c1c5e0952dfb1f7748cdad9789fd2a2ae8dc7348 # crib-deploy-environment@2.1.1 + uses: smartcontractkit/.github/actions/crib-deploy-environment@d4d9ce3fad044642d8d2f7ae5aca9f8c78b0073a # crib-deploy-environment@2.1.2 id: deploy-crib with: github-token: ${{ steps.token.outputs.access-token }} diff --git a/.github/workflows/flakeguard-nightly.yml b/.github/workflows/flakeguard-nightly.yml new file mode 100644 index 00000000000..37c00fa0a8f --- /dev/null +++ b/.github/workflows/flakeguard-nightly.yml @@ -0,0 +1,22 @@ +name: Flakeguard Nightly + +on: + schedule: + # Run every night at 3:00 AM UTC + - cron: '0 3 * * *' + workflow_dispatch: + +jobs: + trigger-flaky-test-detection: + name: Find Flaky Tests + uses: ./.github/workflows/flakeguard.yml + with: + repoUrl: 'https://github.com/smartcontractkit/chainlink' + headRef: 'develop' + projectPath: '.' + maxPassRatio: '1.0' + runAllTests: true + extraArgs: '{ "skipped_tests": "TestChainComponents", "test_repeat_count": "5", "all_tests_runner": "ubuntu22.04-32cores-128GB", "all_tests_runner_count": "3", "run_with_race": "false" }' + slackNotificationAfterTestsChannelId: 'C07TRF65CNS' #flaky-test-detector-notifications + secrets: + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} diff --git a/.github/workflows/flakeguard-on-demand.yml b/.github/workflows/flakeguard-on-demand.yml index 0ac8444a542..fe972894594 100644 --- a/.github/workflows/flakeguard-on-demand.yml +++ b/.github/workflows/flakeguard-on-demand.yml @@ -1,9 +1,6 @@ name: Flakeguard On Demand on: - schedule: - # Run every night at 3:00 AM UTC - - cron: '0 3 * * *' workflow_dispatch: inputs: repoUrl: @@ -52,7 +49,7 @@ on: extraArgs: required: false type: string - default: '{ "skipped_tests": "TestChainComponents", "test_repeat_count": "5", "all_tests_runner": "ubuntu22.04-32cores-128GB", "all_tests_runner_count": "3", "min_pass_ratio": "0", "run_with_race": "false" }' + default: '{ "skipped_tests": "TestChainComponents", "test_repeat_count": "5", "all_tests_runner": "ubuntu22.04-32cores-128GB", "all_tests_runner_count": "3", "run_with_race": "false" }' description: 'JSON of extra arguments for the workflow.' jobs: @@ -68,7 +65,7 @@ jobs: runAllTests: ${{ inputs.runAllTests }} findByTestFilesDiff: ${{ inputs.findByTestFilesDiff }} findByAffectedPackages: ${{ inputs.findByAffectedPackages }} - slackNotificationAfterTestsChannelId: ${{ inputs.slack_notification_after_tests_channel_id }} + slackNotificationAfterTestsChannelId: ${{ inputs.slack_notification_after_tests_channel_id || 'C07TRF65CNS' }} #flaky-test-detector-notifications extraArgs: ${{ inputs.extraArgs }} secrets: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} diff --git a/.github/workflows/flakeguard.yml b/.github/workflows/flakeguard.yml index 8364a5c142a..ecc56e2f291 100644 --- a/.github/workflows/flakeguard.yml +++ b/.github/workflows/flakeguard.yml @@ -13,7 +13,7 @@ on: description: 'The path to the project to run the flaky test detection.' default: '.' baseRef: - required: true + required: false type: string description: 'The base reference or branch to compare changes for detecting flaky tests.' headRef: @@ -60,10 +60,13 @@ env: ALL_TESTS_RUNNER_COUNT: ${{ fromJson(inputs.extraArgs)['all_tests_runner_count'] || '2' }} # The number of GitHub runners to use when running all tests `runAllTests=true`. TEST_REPEAT_COUNT: ${{ fromJson(inputs.extraArgs)['test_repeat_count'] || '5' }} # The number of times each runner should run a test to detect flaky tests. RUN_WITH_RACE: ${{ fromJson(inputs.extraArgs)['run_with_race'] || 'true' }} # Whether to run tests with -race flag. + RUN_WITH_SHUFFLE: ${{ fromJson(inputs.extraArgs)['run_with_shuffle'] || 'false' }} # Whether to run tests with -shuffle flag. + SHUFFLE_SEED: ${{ fromJson(inputs.extraArgs)['shuffle_seed'] || '999' }} # The seed to use when -shuffle flag is enabled. Requires RUN_WITH_SHUFFLE to be true. ALL_TESTS_RUNNER: ${{ fromJson(inputs.extraArgs)['all_tests_runner'] || 'ubuntu22.04-32cores-128GB' }} # The runner to use for running all tests. DEFAULT_RUNNER: 'ubuntu-latest' # The default runner to use for running tests. UPLOAD_ALL_TEST_RESULTS: ${{ fromJson(inputs.extraArgs)['upload_all_test_results'] || 'false' }} # Whether to upload all test results as artifacts. PRINT_FAILED_TESTS: ${{ fromJson(inputs.extraArgs)['print_failed_tests'] || 'false' }} # Whether to print failed tests in the GitHub console. + jobs: get-tests: @@ -98,7 +101,7 @@ jobs: - name: Install flakeguard shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@be06798af83ef6d9f7cf04e8b10a8484520c5061 # flakguard@0.0.1 + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@9e40f2765df01f20b3bf53f0fb3ead920e3a1f4a # flakguard@0.1.0 - name: Find new or updated test packages if: ${{ inputs.runAllTests == false }} @@ -257,11 +260,11 @@ jobs: - name: Install flakeguard shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@be06798af83ef6d9f7cf04e8b10a8484520c5061 # flakguard@0.0.1 + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@9e40f2765df01f20b3bf53f0fb3ead920e3a1f4a # flakguard@0.1.0 - name: Run tests with flakeguard shell: bash - run: flakeguard run --project-path=${{ inputs.projectPath }} --test-packages=${{ matrix.testPackages }} --run-count=${{ env.TEST_REPEAT_COUNT }} --max-pass-ratio=${{ inputs.maxPassRatio }} --race=${{ env.RUN_WITH_RACE }} --skip-tests=${{ env.SKIPPED_TESTS }} --print-failed-tests=${{ env.PRINT_FAILED_TESTS }} --output-json=test-result.json + run: flakeguard run --project-path=${{ inputs.projectPath }} --test-packages=${{ matrix.testPackages }} --run-count=${{ env.TEST_REPEAT_COUNT }} --max-pass-ratio=${{ inputs.maxPassRatio }} --race=${{ env.RUN_WITH_RACE }} --shuffle=${{ env.RUN_WITH_SHUFFLE }} --shuffle-seed=${{ env.SHUFFLE_SEED }} --skip-tests=${{ env.SKIPPED_TESTS }} --print-failed-tests=${{ env.PRINT_FAILED_TESTS }} --output-json=test-result.json env: CL_DATABASE_URL: ${{ env.DB_URL }} @@ -281,6 +284,11 @@ jobs: outputs: test_results: ${{ steps.set_test_results.outputs.results }} steps: + - name: Checkout repository + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + ref: ${{ env.GIT_HEAD_REF }} + - name: Set Pretty Project Path id: set_project_path_pretty run: | @@ -293,21 +301,22 @@ jobs: - name: Download all test result artifacts uses: actions/download-artifact@v4.1.8 with: - path: test_results + path: ci_test_results pattern: test-result-${{ needs.get-tests.outputs.workflow_id }}-* - name: Install flakeguard shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@be06798af83ef6d9f7cf04e8b10a8484520c5061 # flakguard@0.0.1 + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@9e40f2765df01f20b3bf53f0fb3ead920e3a1f4a # flakguard@0.1.0 - name: Set combined test results id: set_test_results shell: bash run: | set -e # Exit immediately if a command exits with a non-zero status. - if [ -d "test_results" ]; then - cd test_results + + if [ -d "ci_test_results" ]; then + cd ci_test_results ls -R . # Fix flakeguard binary path @@ -315,35 +324,69 @@ jobs: export PATH # Use flakeguard to aggregate all test results - flakeguard aggregate-results --results-path . --output-results ../all_tests.json + flakeguard aggregate-results --results-path . --output-results ../all_tests.json --project-path=${{ github.workspace }}/${{ inputs.projectPath }} --codeowners-path=${{ github.workspace }}/.github/CODEOWNERS # Count all tests - ALL_TESTS_COUNT=$(jq 'length' ../all_tests.json) + ALL_TESTS_COUNT=$(jq '.Results | length' ../all_tests.json) echo "All tests count: $ALL_TESTS_COUNT" echo "all_tests_count=$ALL_TESTS_COUNT" >> "$GITHUB_OUTPUT" - # Use flakeguard to filter and output failed tests based on PassRatio threshold - flakeguard aggregate-results --filter-failed=true --threshold "${{ inputs.runThreshold }}" --min-pass-ratio=${{ env.MIN_PASS_RATIO }} --results-path . --output-results ../failed_tests.json --output-logs ../failed_test_logs.json + # Use flakeguard to filter and output failed tests based on MaxPassRatio + flakeguard aggregate-results --filter-failed=true --max-pass-ratio=${{ inputs.maxPassRatio }} --results-path . --output-results ../failed_tests.json --output-logs ../failed_test_logs.json --project-path=${{ github.workspace }}/${{ inputs.projectPath }} --codeowners-path=${{ github.workspace }}/.github/CODEOWNERS # Count failed tests if [ -f "../failed_tests.json" ]; then - FAILED_TESTS_COUNT=$(jq 'length' ../failed_tests.json) + FAILED_TESTS_COUNT=$(jq '.Results | length' ../failed_tests.json) else FAILED_TESTS_COUNT=0 fi echo "Failed tests count: $FAILED_TESTS_COUNT" echo "failed_tests_count=$FAILED_TESTS_COUNT" >> "$GITHUB_OUTPUT" + + # Calculate failed ratio (failed / non-failed tests ratio in %) + if [ "$ALL_TESTS_COUNT" -gt 0 ]; then + NON_FAILED_COUNT=$((ALL_TESTS_COUNT - FAILED_TESTS_COUNT)) + + if [ "$NON_FAILED_COUNT" -gt 0 ]; then + FAILED_RATIO=$(awk "BEGIN {printf \"%.2f\", ($FAILED_TESTS_COUNT / $NON_FAILED_COUNT) * 100}") + else + FAILED_RATIO=0 + fi + else + NON_FAILED_COUNT=0 + FAILED_RATIO=0 + fi + echo "Failed tests ratio: $FAILED_RATIO%" + echo "failed_ratio=$FAILED_RATIO" >> "$GITHUB_OUTPUT" else echo "No test results directory found." echo "all_tests_count=0" >> "$GITHUB_OUTPUT" echo "failed_tests_count=0" >> "$GITHUB_OUTPUT" - fi + echo "failed_ratio=0" >> "$GITHUB_OUTPUT" + fi - - name: Calculate Flakiness Threshold Percentage - id: calculate_threshold + - name: Tests Summary + if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} run: | - threshold_percentage=$(echo '${{ inputs.runThreshold }}' | awk '{printf "%.0f", $1 * 100}') - echo "threshold_percentage=$threshold_percentage" >> $GITHUB_OUTPUT + FILE_SIZE=$(wc -c < all_tests.md) + echo "File size: $FILE_SIZE bytes" + SIZE_LIMIT=$((1024 * 1024)) + + if [ "$FILE_SIZE" -le "$SIZE_LIMIT" ]; then + cat all_tests.md >> $GITHUB_STEP_SUMMARY + else + echo "**We found flaky tests, so many flaky tests that the summary is too large for github actions step summaries!**" >> $GITHUB_STEP_SUMMARY + echo "**Please see logs, or the attached `all-summary.md` artifact**" >> $GITHUB_STEP_SUMMARY + cat all_tests.md + fi + + - name: Upload All Tests Summary as Artifact + if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} + uses: actions/upload-artifact@v4.4.3 + with: + path: all_tests.md + name: all-summary.md + retention-days: 90 - name: Upload All Test Results as Artifact if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} @@ -351,7 +394,15 @@ jobs: with: path: all_tests.json name: all-test-results.json - retention-days: 7 + retention-days: 90 + + - name: Upload Failed Tests Summary as Artifact + if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} + uses: actions/upload-artifact@v4.4.3 + with: + path: failed_tests.md + name: failed-summary.md + retention-days: 90 - name: Upload Failed Test Results as Artifact if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} @@ -359,7 +410,7 @@ jobs: with: path: failed_tests.json name: failed-test-results.json - retention-days: 7 + retention-days: 90 - name: Upload Failed Test Logs as Artifact if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} @@ -367,7 +418,7 @@ jobs: with: path: failed_test_logs.json name: failed-test-logs.json - retention-days: 7 + retention-days: 90 - name: Upload All Test Results as Artifact if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 && env.UPLOAD_ALL_TEST_RESULTS == 'true' }} @@ -375,154 +426,17 @@ jobs: with: path: all_tests.json name: all-test-results.json - retention-days: 7 - - - name: Create ASCII table with failed test results - if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} - shell: bash - run: | - jq -r '["TestPackage", "TestName", "PassRatio", "RunCount", "Skipped"], ["---------", "---------", "---------", "---------", "---------"], (.[] | [.TestPackage, .TestName, .PassRatioPercentage, .Runs, .Skipped]) | @tsv' failed_tests.json | column -t -s$'\t' > failed_tests_ascii.txt - cat failed_tests_ascii.txt - - - name: Create ASCII table with all test results - if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} - shell: bash - run: | - jq -r '["TestPackage", "TestName", "PassRatio", "RunCount", "Skipped"], ["---------", "---------", "---------", "---------", "---------"], (.[] | [.TestPackage, .TestName, .PassRatioPercentage, .Runs, .Skipped]) | @tsv' all_tests.json | column -t -s$'\t' > all_tests_ascii.txt - cat all_tests_ascii.txt - - - name: Create GitHub Summary (General) - run: | - echo "## Flaky Test Detection Report for ${{ steps.set_project_path_pretty.outputs.path }} Project" >> $GITHUB_STEP_SUMMARY - - - name: Create GitHub Summary (Comparative Test Analysis) - if: ${{ inputs.runAllTests == false }} - run: | - echo "### Comparative Test Analysis" >> $GITHUB_STEP_SUMMARY - echo "Checked changes between \`${{ inputs.baseRef }}\` and \`${{ env.GIT_HEAD_REF }}\`. See all changes [here](${{ inputs.repoUrl }}/compare/${{ inputs.baseRef }}...${{ needs.get-tests.outputs.git_head_sha }}#files_bucket)." >> $GITHUB_STEP_SUMMARY - - - name: Create GitHub Summary (All Tests) - if: ${{ inputs.runAllTests == 'true' }} - run: | - echo "### Running All Tests" >> $GITHUB_STEP_SUMMARY - echo "All tests are being executed as \`runAllTests\` is set to true." >> $GITHUB_STEP_SUMMARY - - - name: Append Changed Test Files to GitHub Summary - if: ${{ needs.get-tests.outputs.changed_test_files != '' && inputs.findByTestFilesDiff && !inputs.findByAffectedPackages }} - run: | - echo "### Changed Test Files" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - IFS=' ' read -ra ADDR <<< "${{ needs.get-tests.outputs.changed_test_files }}" - for file in "${ADDR[@]}"; do - echo "$file" >> $GITHUB_STEP_SUMMARY - done - echo '```' >> $GITHUB_STEP_SUMMARY - - - name: Append Affected Test Packages to GitHub Summary - if: ${{ needs.get-tests.outputs.affected_test_packages != '' }} - run: | - echo "### Affected Test Packages" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - IFS=' ' read -ra ADDR <<< "${{ needs.get-tests.outputs.affected_test_packages }}" - for package in "${ADDR[@]}"; do - echo "$package" >> $GITHUB_STEP_SUMMARY - done - echo '```' >> $GITHUB_STEP_SUMMARY - - - name: Read Failed Tests File - if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} - id: read_failed_tests - run: | - file_content=$(cat failed_tests_ascii.txt) - echo "failed_tests_content<> $GITHUB_OUTPUT - echo "$file_content" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - - name: Calculate Test Repeat Count - id: calculate_test_repeat_count - shell: bash - run: | - # Convert environment variables to integers - ALL_TESTS_RUNNER_COUNT=${{ env.ALL_TESTS_RUNNER_COUNT }} - TEST_REPEAT_COUNT=${{ env.TEST_REPEAT_COUNT }} - - # If runAllTests input is true, multiply the number of runners by the test repeat count as each runner runs all tests - # Otherwise, use the test repeat count as each runner runs unique tests - if [[ "${{ inputs.runAllTests }}" == "true" ]]; then - test_repeat_count=$(( ALL_TESTS_RUNNER_COUNT * TEST_REPEAT_COUNT )) - else - test_repeat_count=$TEST_REPEAT_COUNT - fi - echo "test_repeat_count=$test_repeat_count" >> $GITHUB_OUTPUT - - - name: Append Flaky Tests to GitHub Summary - if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} - run: | - threshold_percentage=$(echo "${{ inputs.runThreshold }}" | awk '{printf "%.2f", $1 * 100}') - min_pass_ratio_percentage=$(echo "${{ env.MIN_PASS_RATIO }}" | awk '{printf "%.2f", $1 * 100}') - echo "### Flaky Tests :x:" >> $GITHUB_STEP_SUMMARY - echo "Ran ${{ steps.set_test_results.outputs.all_tests_count }} unique tests ${{ steps.calculate_test_repeat_count.outputs.test_repeat_count }} times. Below are the tests identified as flaky, with a pass ratio lower than the ${threshold_percentage}% threshold:" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - cat failed_tests_ascii.txt >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - echo "For detailed logs of the failed tests, please refer to the failed-test-results.json and failed-test-logs.json files in the Artifacts section at the bottom of the page. failed-test-logs.json contains all outputs from failed tests." >> $GITHUB_STEP_SUMMARY - - - name: Append Success Note if No Flaky Tests Found - if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 && fromJson(steps.set_test_results.outputs.failed_tests_count) == 0 }} - run: | - echo "### No Flaky Tests Found! :white_check_mark:" >> $GITHUB_STEP_SUMMARY - echo "Ran \`${{ steps.set_test_results.outputs.all_tests_count }}\` unique tests ${{ steps.calculate_test_repeat_count.outputs.test_repeat_count }} times and found no flakes." >> $GITHUB_STEP_SUMMARY - - - name: Append Additional Info to GitHub Summary - if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} - run: | - echo "### Settings" >> $GITHUB_STEP_SUMMARY - threshold_percentage=$(echo "${{ inputs.runThreshold }}" | awk '{printf "%.2f", $1 * 100}') - min_pass_ratio_percentage=$(echo "${{ env.MIN_PASS_RATIO }}" | awk '{printf "%.2f", $1 * 100}') - echo "| **Setting** | **Value** |" >> $GITHUB_STEP_SUMMARY - echo "|-------------------------|------------|" >> $GITHUB_STEP_SUMMARY - echo "| Go Project | ${{ steps.set_project_path_pretty.outputs.path }} |" >> $GITHUB_STEP_SUMMARY - echo "| Minimum Pass Ratio | ${min_pass_ratio_percentage}% |" >> $GITHUB_STEP_SUMMARY - echo "| Flakiness Threshold | ${threshold_percentage}% |" >> $GITHUB_STEP_SUMMARY - echo "| Test Run Count | ${{ steps.calculate_test_repeat_count.outputs.test_repeat_count }} |" >> $GITHUB_STEP_SUMMARY - echo "| Race Detection | ${{ env.RUN_WITH_RACE }} |" >> $GITHUB_STEP_SUMMARY - echo "| Excluded Tests | ${{ env.SKIPPED_TESTS }} |" >> $GITHUB_STEP_SUMMARY - - - name: Append No Tests Found Message to GitHub Summary - if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) == 0 }} - run: | - echo "### No Tests To Execute" >> $GITHUB_STEP_SUMMARY - echo "No updated or new Go tests found for ${{ steps.set_project_path_pretty.outputs.path }} project. The flaky detector will not run." >> $GITHUB_STEP_SUMMARY + retention-days: 90 - name: Post comment on PR if flaky tests found if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 && github.event_name == 'pull_request' }} uses: actions/github-script@v7 - env: - MESSAGE_BODY_1: '### Flaky Test Detector for `${{ steps.set_project_path_pretty.outputs.path }}` project has failed :x:' - MESSAGE_BODY_2: 'Ran new or updated tests between `${{ inputs.baseRef }}` and ${{ needs.get-tests.outputs.git_head_sha }} (`${{ env.GIT_HEAD_REF }}`).' - MESSAGE_BODY_3: ${{ format('[View Flaky Detector Details]({0}/{1}/actions/runs/{2}) | [Compare Changes]({3}/compare/{4}...{5}#files_bucket)', github.server_url, github.repository, github.run_id, inputs.repoUrl, github.base_ref, needs.get-tests.outputs.git_head_sha) }} - MESSAGE_BODY_4: '#### Flaky Tests' - MESSAGE_BODY_5: 'Ran ${{ steps.set_test_results.outputs.all_tests_count }} unique tests. Below are the tests identified as flaky, with a pass ratio lower than the ${{ steps.calculate_threshold.outputs.threshold_percentage }}% threshold:' - MESSAGE_BODY_6: '```' - MESSAGE_BODY_7: '${{ steps.read_failed_tests.outputs.failed_tests_content }}' - MESSAGE_BODY_8: '```' + continue-on-error: true with: script: | + const fs = require('fs'); const prNumber = context.payload.pull_request.number; - - const commentBody = `${process.env.MESSAGE_BODY_1} - - ${process.env.MESSAGE_BODY_2} - - ${process.env.MESSAGE_BODY_3} - - ${process.env.MESSAGE_BODY_4} - - ${process.env.MESSAGE_BODY_5} - - ${process.env.MESSAGE_BODY_6} - ${process.env.MESSAGE_BODY_7} - ${process.env.MESSAGE_BODY_8}`; + const commentBody = fs.readFileSync('all_tests.md', 'utf8'); await github.rest.issues.createComment({ owner: context.repo.owner, @@ -531,9 +445,61 @@ jobs: body: commentBody }); - - name: Send Slack message + - name: Send Slack message for failed tests + if: ${{ inputs.slackNotificationAfterTestsChannelId != '' && fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - if: ${{ inputs.slackNotificationAfterTestsChannelId != '' && fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + with: + channel-id: ${{ inputs.slackNotificationAfterTestsChannelId }} + payload: | + { + "attachments": [ + { + "color": "#C62828", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Flaky Test Detector for `${{ steps.set_project_path_pretty.outputs.path }}` project - ${{ contains(join(needs.*.result, ','), 'failure') && 'Failed :x:' || contains(join(needs.*.result, ','), 'cancelled') && 'Was cancelled :warning:' || 'Passed :white_check_mark:' }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "${{ inputs.runAllTests == true && format('Ran all tests for `{0}` branch.', inputs.headRef) || format('Ran changed tests between `{0}` and `{1}` (`{2}`).', inputs.baseRef, needs.get-tests.outputs.git_head_short_sha, env.GIT_HEAD_REF) }}" + } + }, + { + "type": "section", + "fields": [ + { + "type": "mrkdwn", + "text": "Total Failed Tests: ${{ steps.set_test_results.outputs.failed_tests_count }}" + }, + { + "type": "mrkdwn", + "text": "Failed to Non-Failed Ratio: ${{ steps.set_test_results.outputs.failed_ratio }}%" + } + ] + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "${{ format('<{0}/{1}/actions/runs/{2}|View Flaky Detector Details> | <{3}/compare/{4}...{5}#files_bucket|Compare Changes>{6}', github.server_url, github.repository, github.run_id, inputs.repoUrl, inputs.baseRef, needs.get-tests.outputs.git_head_sha, github.event_name == 'pull_request' && format(' | <{0}|View PR>', github.event.pull_request.html_url) || '') }}" + } + } + ] + } + ] + } + + - name: Send general Slack message + uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 + if: ${{ inputs.slackNotificationAfterTestsChannelId != '' && fromJson(steps.set_test_results.outputs.failed_tests_count) == 0 && fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} id: slack env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} @@ -556,14 +522,14 @@ jobs: "type": "section", "text": { "type": "mrkdwn", - "text": "Ran changed tests between `${{ inputs.baseRef }}` and `${{ needs.get-tests.outputs.git_head_short_sha }}` (`${{ env.GIT_HEAD_REF }}`)." + "text": "${{ inputs.runAllTests == true && format('Ran all tests for `{0}` branch.', env.GIT_HEAD_REF) || format('Ran changed tests between `{0}` and `{1}` (`{2}`).', inputs.baseRef, needs.get-tests.outputs.git_head_short_sha, env.GIT_HEAD_REF) }}" } }, { "type": "section", "text": { "type": "mrkdwn", - "text": "${{ format('<{0}/{1}/actions/runs/{2}|View Flaky Detector Details> | <{3}/compare/{4}...{5}#files_bucket|Compare Changes>{6}', github.server_url, github.repository, github.run_id, inputs.repoUrl, inputs.baseRef, needs.get-tests.outputs.git_head_sha, github.event_name == 'pull_request' && format(' | <{0}|View PR>', github.event.pull_request.html_url) || '') }}" + "text": "${{ inputs.runAllTests == true && format('<{0}/{1}/actions/runs/{2}|View Flaky Detector Details>', github.server_url, github.repository, github.run_id) || format('<{0}/{1}/actions/runs/{2}|View Flaky Detector Details> | <{3}/compare/{4}...{5}#files_bucket|Compare Changes>{6}', github.server_url, github.repository, github.run_id, inputs.repoUrl, inputs.baseRef, needs.get-tests.outputs.git_head_sha, github.event_name == 'pull_request' && format(' | <{0}|View PR>', github.event.pull_request.html_url) || '') }}" } } ] diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index ea0016014a7..bac453eb044 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -296,7 +296,7 @@ jobs: contents: read needs: [build-chainlink, changes] if: github.event_name == 'pull_request' && (needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: workflow_name: Run CCIP E2E Tests For PR chainlink_version: ${{ inputs.evm-ref || github.sha }} @@ -306,6 +306,7 @@ jobs: upload_cl_node_coverage_artifact: true upload_cl_node_coverage_artifact_prefix: cl_node_coverage_data_ enable_otel_traces_for_ocr2_plugins: ${{ contains(join(github.event.pull_request.labels.*.name, ' '), 'enable tracing') }} + team: "CCIP" secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -337,7 +338,7 @@ jobs: contents: read needs: [build-chainlink, changes] if: github.event_name == 'merge_group' && (needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: workflow_name: Run CCIP E2E Tests For Merge Queue chainlink_version: ${{ inputs.evm-ref || github.sha }} @@ -347,6 +348,7 @@ jobs: upload_cl_node_coverage_artifact: true upload_cl_node_coverage_artifact_prefix: cl_node_coverage_data_ enable_otel_traces_for_ocr2_plugins: ${{ contains(join(github.event.pull_request.labels.*.name, ' '), 'enable tracing') }} + team: "CCIP" secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -592,6 +594,7 @@ jobs: ] env: CONTRACT_ARTIFACTS_PATH: contracts/target/deploy + GOTOOLCHAIN: auto steps: - name: Checkout the repo if: (needs.changes.outputs.core_changes == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml index ac97d3c6355..a9a8c3c2a2f 100644 --- a/.github/workflows/on-demand-ocr-soak-test.yml +++ b/.github/workflows/on-demand-ocr-soak-test.yml @@ -34,18 +34,23 @@ on: slackMemberID: description: Slack Member ID (Not your @) required: true - default: U01A2B2C3D4 + default: U01A2B2C3D4 + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + type: string jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: test_path: .github/e2e-tests.yml test_ids: ${{ inputs.testToRun}} test_config_override_path: ${{ inputs.test_config_override_path }} chainlink_version: ${{ inputs.chainlink_version }} SLACK_USER: ${{ inputs.slackMemberID }} + team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.mockery.yaml b/.mockery.yaml index 70b7a9947f6..dd9024cc066 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -234,6 +234,7 @@ packages: config: filename: starknet.go VRF: + Workflow: github.com/smartcontractkit/chainlink/v2/core/services/ocr: interfaces: OCRContractTrackerDB: @@ -347,7 +348,7 @@ packages: Codec: config: dir: core/services/relay/evm/mocks - ChainWriter: + ContractWriter: github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp: config: dir: core/gethwrappers/ccip/mocks/ diff --git a/README.md b/README.md index e7c21c1e094..2dc51e9cf0d 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ regarding Chainlink social accounts, news, and networking. ## Build Chainlink -1. [Install Go 1.22](https://golang.org/doc/install), and add your GOPATH's [bin directory to your PATH](https://golang.org/doc/code.html#GOPATH) +1. [Install Go 1.23](https://golang.org/doc/install), and add your GOPATH's [bin directory to your PATH](https://golang.org/doc/code.html#GOPATH) - Example Path for macOS `export PATH=$GOPATH/bin:$PATH` & `export GOPATH=/Users/$USER/go` 2. Install [NodeJS v20](https://nodejs.org/en/download/package-manager/) & [pnpm v9 via npm](https://pnpm.io/installation#using-npm). - It might be easier long term to use [nvm](https://nodejs.org/en/download/package-manager/#nvm) to switch between node versions for different projects. For example, assuming $NODE_VERSION was set to a valid version of NodeJS, you could run: `nvm install $NODE_VERSION && nvm use $NODE_VERSION` diff --git a/common/client/transaction_sender.go b/common/client/transaction_sender.go index cd2ce96c5b2..5f58682142f 100644 --- a/common/client/transaction_sender.go +++ b/common/client/transaction_sender.go @@ -93,6 +93,8 @@ type TransactionSender[TX any, RESULT SendTxResult, CHAIN_ID types.ID, RPC SendT // * Otherwise, returns any (effectively random) of the errors. func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ctx context.Context, tx TX) RESULT { var result RESULT + ctx, cancel := txSender.chStop.Ctx(ctx) + defer cancel() if !txSender.IfStarted(func() { txResults := make(chan RESULT) txResultsToReport := make(chan RESULT) @@ -103,8 +105,6 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ct if isSendOnly { txSender.wg.Add(1) go func(ctx context.Context) { - ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) - defer cancel() defer txSender.wg.Done() // Send-only nodes' results are ignored as they tend to return false-positive responses. // Broadcast to them is necessary to speed up the propagation of TX in the network. @@ -117,8 +117,9 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ct healthyNodesNum++ primaryNodeWg.Add(1) go func(ctx context.Context) { - ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) - defer cancel() + // Broadcasting transaction and results reporting for invariant detection are background jobs that must be detached from + // callers cancellation. + // Results reporting to SendTransaction caller must respect caller's context to avoid goroutine leak. defer primaryNodeWg.Done() r := txSender.broadcastTxAsync(ctx, rpc, tx) select { @@ -128,6 +129,8 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ct case txResults <- r: } + ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) + defer cancel() select { case <-ctx.Done(): txSender.lggr.Debugw("Failed to send tx results to report", "err", ctx.Err()) @@ -151,8 +154,13 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ct return } + if healthyNodesNum == 0 { + result = txSender.newResult(ErroringNodeError) + return + } + txSender.wg.Add(1) - go txSender.reportSendTxAnomalies(ctx, tx, txResultsToReport) + go txSender.reportSendTxAnomalies(tx, txResultsToReport) result = txSender.collectTxResults(ctx, tx, healthyNodesNum, txResults) }) { @@ -163,6 +171,9 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ct } func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) broadcastTxAsync(ctx context.Context, rpc RPC, tx TX) RESULT { + // broadcast is a background job, so always detach from caller's cancellation + ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) + defer cancel() result := rpc.SendTransaction(ctx, tx) txSender.lggr.Debugw("Node sent transaction", "tx", tx, "err", result.Error()) if !slices.Contains(sendTxSuccessfulCodes, result.Code()) && ctx.Err() == nil { @@ -171,7 +182,7 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) broadcastTxAsync(c return result } -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) reportSendTxAnomalies(ctx context.Context, tx TX, txResults <-chan RESULT) { +func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) reportSendTxAnomalies(tx TX, txResults <-chan RESULT) { defer txSender.wg.Done() resultsByCode := sendTxResults[RESULT]{} // txResults eventually will be closed @@ -179,8 +190,17 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) reportSendTxAnomal resultsByCode[txResult.Code()] = append(resultsByCode[txResult.Code()], txResult) } + select { + case <-txSender.chStop: + // it's ok to receive no results if txSender is closing. Return early to prevent false reporting of invariant violation. + if len(resultsByCode) == 0 { + return + } + default: + } + _, criticalErr := aggregateTxResults[RESULT](resultsByCode) - if criticalErr != nil && ctx.Err() == nil { + if criticalErr != nil { txSender.lggr.Criticalw("observed invariant violation on SendTransaction", "tx", tx, "resultsByCode", resultsByCode, "err", criticalErr) PromMultiNodeInvariantViolations.WithLabelValues(txSender.chainFamily, txSender.chainID.String(), criticalErr.Error()).Inc() } @@ -218,9 +238,6 @@ func aggregateTxResults[RESULT any](resultsByCode sendTxResults[RESULT]) (result } func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) collectTxResults(ctx context.Context, tx TX, healthyNodesNum int, txResults <-chan RESULT) RESULT { - if healthyNodesNum == 0 { - return txSender.newResult(ErroringNodeError) - } requiredResults := int(math.Ceil(float64(healthyNodesNum) * sendTxQuorum)) errorsByCode := sendTxResults[RESULT]{} var softTimeoutChan <-chan time.Time diff --git a/common/client/transaction_sender_test.go b/common/client/transaction_sender_test.go index e9869610828..656791b7e86 100644 --- a/common/client/transaction_sender_test.go +++ b/common/client/transaction_sender_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -293,6 +294,27 @@ func TestTransactionSender_SendTransaction(t *testing.T) { require.NoError(t, result.Error()) require.Equal(t, Successful, result.Code()) }) + t.Run("All background jobs stop even if RPC returns result after soft timeout", func(t *testing.T) { + chainID := types.RandomID() + expectedError := errors.New("transaction failed") + fastNode := newNode(t, expectedError, nil) + + // hold reply from the node till SendTransaction returns result + sendTxContext, sendTxCancel := context.WithCancel(tests.Context(t)) + slowNode := newNode(t, errors.New("transaction failed"), func(_ mock.Arguments) { + <-sendTxContext.Done() + }) + + lggr := logger.Test(t) + + _, txSender := newTestTransactionSender(t, chainID, lggr, []Node[types.ID, TestSendTxRPCClient]{fastNode, slowNode}, nil) + result := txSender.SendTransaction(sendTxContext, nil) + sendTxCancel() + require.EqualError(t, result.Error(), expectedError.Error()) + // TxSender should stop all background go routines after SendTransaction is done and before test is done. + // Otherwise, it signals that we have a goroutine leak. + txSender.wg.Wait() + }) } func TestTransactionSender_SendTransaction_aggregateTxResults(t *testing.T) { diff --git a/contracts/.changeset/bright-jokes-kiss.md b/contracts/.changeset/bright-jokes-kiss.md new file mode 100644 index 00000000000..9aac95d84c9 --- /dev/null +++ b/contracts/.changeset/bright-jokes-kiss.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': patch +--- + +add legacy fallback to RMN + + +PR issue: CCIP-4261 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/chilly-rockets-share.md b/contracts/.changeset/chilly-rockets-share.md new file mode 100644 index 00000000000..ef5d3e454d7 --- /dev/null +++ b/contracts/.changeset/chilly-rockets-share.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': patch +--- + +Moves all audited L2EP contracts out from dev directory + + +PR issue: SHIP-3191 + +Solidity Review issue: SHIP-4050 \ No newline at end of file diff --git a/contracts/.changeset/fluffy-eels-tan.md b/contracts/.changeset/fluffy-eels-tan.md new file mode 100644 index 00000000000..967e7e2f72d --- /dev/null +++ b/contracts/.changeset/fluffy-eels-tan.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': patch +--- + +Add token address to TokenHandlingError + + +PR issue: CCIP-4174 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/mean-masks-poke.md b/contracts/.changeset/mean-masks-poke.md new file mode 100644 index 00000000000..00d8434e226 --- /dev/null +++ b/contracts/.changeset/mean-masks-poke.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': patch +--- + +#added new function to CCIPReaderTester getLatestPriceSequenceNumber + + +PR issue: CCIP-4239 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/perfect-bears-clean.md b/contracts/.changeset/perfect-bears-clean.md new file mode 100644 index 00000000000..0f8284037f5 --- /dev/null +++ b/contracts/.changeset/perfect-bears-clean.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +Add BalanceReader contract for native balance reads through a contract diff --git a/contracts/.changeset/rude-badgers-tickle.md b/contracts/.changeset/rude-badgers-tickle.md new file mode 100644 index 00000000000..4dddf8d430e --- /dev/null +++ b/contracts/.changeset/rude-badgers-tickle.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +reduce length of reportContext in OCR3 diff --git a/contracts/.changeset/tender-lemons-punch.md b/contracts/.changeset/tender-lemons-punch.md new file mode 100644 index 00000000000..cac2e7ea0cf --- /dev/null +++ b/contracts/.changeset/tender-lemons-punch.md @@ -0,0 +1,9 @@ +--- +'@chainlink/contracts': minor +--- + +#internal Add supportsInterface to FeeQuoter for Keystone + +PR issue: CCIP-4359 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/three-dogs-return.md b/contracts/.changeset/three-dogs-return.md new file mode 100644 index 00000000000..c0b4a48f7f6 --- /dev/null +++ b/contracts/.changeset/three-dogs-return.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +extra validation on decimal logic in token pools diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 487265ef580..955000e016f 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -4,23 +4,23 @@ ARMProxy_isCursed:test_call_ARMCallEmptyContract_Revert() (gas: 19412) ARMProxy_isCursed:test_isCursed_RevertReasonForwarded_Revert() (gas: 45210) ARMProxy_setARM:test_SetARM() (gas: 16599) ARMProxy_setARM:test_SetARMzero() (gas: 11275) -BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27357) +BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27346) BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 54878) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244461) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244452) BurnFromMintTokenPool_lockOrBurn:test_setup_Success() (gas: 24210) -BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27497) +BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27486) BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 54878) -BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 242361) +BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 242352) BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17852) -BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 27298) +BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 27287) BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 54624) -BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 109448) -BurnMintWithLockReleaseFlagTokenPool_lockOrBurn:test_LockOrBurn_CorrectReturnData_Success() (gas: 242814) -BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27357) +BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 109426) +BurnMintWithLockReleaseFlagTokenPool_lockOrBurn:test_LockOrBurn_CorrectReturnData_Success() (gas: 242805) +BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27346) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 54878) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244505) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244496) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24223) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2077713) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2077779) CCIPHome__validateConfig:test__validateConfigLessTransmittersThanSigners_Success() (gas: 332619) CCIPHome__validateConfig:test__validateConfigSmallerFChain_Success() (gas: 458568) CCIPHome__validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 289191) @@ -68,7 +68,7 @@ CCIPHome_setCandidate:test_setCandidate_success() (gas: 1365439) CCIPHome_supportsInterface:test_supportsInterface_success() (gas: 9885) DefensiveExampleTest:test_HappyPath_Success() (gas: 200540) DefensiveExampleTest:test_Recovery() (gas: 425013) -E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1512521) +E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1512127) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96980) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49812) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17479) @@ -119,114 +119,113 @@ FactoryBurnMintERC20_mint:test_SenderNotMinter_Reverts() (gas: 11405) FactoryBurnMintERC20_supportsInterface:test_SupportsInterface_Success() (gas: 11538) FactoryBurnMintERC20_transfer:test_InvalidAddress_Reverts() (gas: 10701) FactoryBurnMintERC20_transfer:test_Transfer_Success() (gas: 42482) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16824) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16737) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16791) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 41195) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroInput_Success() (gas: 12541) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 140643) -FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 162508) -FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12241) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11564) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54904) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 45323) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12456) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 88930) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13324) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17413) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12327) -FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106573) -FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110923) -FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 110998) -FeeQuoter_constructor:test_Setup_Success() (gas: 4974931) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16846) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16759) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16813) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 41239) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroInput_Success() (gas: 12563) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 140709) +FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 162719) +FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12263) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11476) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54860) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 45257) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12368) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 89062) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13346) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17435) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12349) +FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106632) +FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110982) +FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111057) +FeeQuoter_constructor:test_Setup_Success() (gas: 5011219) FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 68416) FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 29300) -FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 96323) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14835) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20944) +FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 96433) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14857) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20988) FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 73071) FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 26476) -FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled_Success() (gas: 112021) +FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled_Success() (gas: 112065) FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16184) -FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 109131) -FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 68015) -FeeQuoter_getTokenPrice:test_GetTokenPrice_LocalMoreRecent_Success() (gas: 33463) -FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78498) -FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 37372) -FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 35151) -FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28241) -FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 96218) -FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20702) -FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28049) -FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28094) -FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40887) -FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29801) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 109175) +FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 68059) +FeeQuoter_getTokenPrice:test_GetTokenPrice_LocalMoreRecent_Success() (gas: 33529) +FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78516) +FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 37307) +FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 35086) +FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28176) +FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 96089) +FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20615) +FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27984) +FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28029) +FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40822) +FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29736) FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18465) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 83208) -FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 53548) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 239604) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 83340) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 53570) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 239736) FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22668) FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29966) FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100417) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 143112) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 143246) FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21280) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 114464) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 114510) FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 23495) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63843) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1897830) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 1897788) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 1877907) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 1897562) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 1897766) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 1897578) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 65210) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 65090) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58872) -FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 1897204) -FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61821) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116926) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14160) -FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 1895881) -FeeQuoter_onReport:test_OnReport_StaleUpdate_SkipPriceUpdate_Success() (gas: 43936) -FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23657) -FeeQuoter_onReport:test_onReport_Success() (gas: 80700) -FeeQuoter_onReport:test_onReport_TokenNotSupported_Revert() (gas: 23024) -FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 27202) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17448) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21620) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18680) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18220) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18534) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18657) -FeeQuoter_processMessageArgs:test_applyTokensTransferFeeConfigUpdates_InvalidFeeRange_Revert() (gas: 21454) -FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidEVMAddressDestToken_Revert() (gas: 44930) -FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidExtraArgs_Revert() (gas: 19986) -FeeQuoter_processMessageArgs:test_processMessageArgs_MalformedEVMExtraArgs_Revert() (gas: 20383) -FeeQuoter_processMessageArgs:test_processMessageArgs_MessageFeeTooHigh_Revert() (gas: 17954) -FeeQuoter_processMessageArgs:test_processMessageArgs_SourceTokenDataTooLarge_Revert() (gas: 123251) -FeeQuoter_processMessageArgs:test_processMessageArgs_TokenAmountArraysMismatching_Revert() (gas: 42192) -FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2_Success() (gas: 28658) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount_Success() (gas: 29999) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData_Success() (gas: 76449) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1_Success() (gas: 28256) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs_Success() (gas: 26115) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount_Success() (gas: 19573) -FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12176) -FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23917) -FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 28604) -FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74711) -FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 145804) -FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 52421) -FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 66335) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63909) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1897852) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 1897810) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 1877929) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 1897584) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 1897788) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 1897600) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 65232) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 65112) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58894) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 1897226) +FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61843) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116970) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14182) +FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 1895903) +FeeQuoter_onReport:test_OnReport_SkipPriceUpdateWhenStaleUpdateReceived() (gas: 52614) +FeeQuoter_onReport:test_onReport() (gas: 89071) +FeeQuoter_onReport:test_onReport_withKeystoneForwarderContract() (gas: 122700) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17381) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21553) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18613) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18153) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18467) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18590) +FeeQuoter_processMessageArgs:test_applyTokensTransferFeeConfigUpdates_InvalidFeeRange_Revert() (gas: 21476) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidEVMAddressDestToken_Revert() (gas: 44974) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidExtraArgs_Revert() (gas: 20008) +FeeQuoter_processMessageArgs:test_processMessageArgs_MalformedEVMExtraArgs_Revert() (gas: 20405) +FeeQuoter_processMessageArgs:test_processMessageArgs_MessageFeeTooHigh_Revert() (gas: 17976) +FeeQuoter_processMessageArgs:test_processMessageArgs_SourceTokenDataTooLarge_Revert() (gas: 123405) +FeeQuoter_processMessageArgs:test_processMessageArgs_TokenAmountArraysMismatching_Revert() (gas: 42236) +FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2_Success() (gas: 28702) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount_Success() (gas: 30021) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData_Success() (gas: 76515) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1_Success() (gas: 28300) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs_Success() (gas: 26159) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount_Success() (gas: 19595) +FeeQuoter_supportsInterface:test_SupportsInterface_Success() (gas: 13263) +FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12198) +FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23872) +FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 28648) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74816) +FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 145691) +FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 52443) +FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 66423) FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 20124) -FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 93475) -FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 53098) +FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 93563) +FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 53142) FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12431) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10688) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 4035395) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10884) -FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6819) -FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6545) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10710) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 4057945) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10906) +FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6841) +FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6567) HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 176837) HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_transferLiquidity_Success() (gas: 166986) HybridLockReleaseUSDCTokenPool_lockOrBurn:test_PrimaryMechanism_Success() (gas: 135860) @@ -236,15 +235,15 @@ HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_thenSwitch HybridLockReleaseUSDCTokenPool_releaseOrMint:test_OnLockReleaseMechanism_Success() (gas: 213127) HybridLockReleaseUSDCTokenPool_releaseOrMint:test_WhileMigrationPause_Revert() (gas: 109646) HybridLockReleaseUSDCTokenPool_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 265910) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3053405) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3099863) LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29734) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 80647) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 80625) LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59227) -LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3049734) +LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3096192) LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11511) -LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 74108) +LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 74100) LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 54745) -LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 223273) +LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 223256) LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 10936) LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18115) LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10250) @@ -283,27 +282,27 @@ MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2093583) MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30794) MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 48169) MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15907) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17602) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21630) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17624) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21652) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14636) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210571) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 58451) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210637) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 58473) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17791) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 45202) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 46470) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 76911) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308951) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 50636) -MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 51287) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 46514) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 76999) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 309039) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 50680) +MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 51331) MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19375) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15914) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210291) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60244) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210357) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60266) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 47025) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 48261) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 77918) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308897) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 52406) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 48305) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 78006) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308985) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 52450) MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 10967) MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19190) MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10642) @@ -334,34 +333,34 @@ MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112357) MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254293) MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 861787) MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 476186) -MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42957) -MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48640) -MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 77185) -MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65925) -MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33494) -MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79889) -MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33686) -MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47188) -MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25711) -MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18722) -MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24299) -MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61298) -MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39952) -MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 33026) +MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42765) +MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48348) +MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76893) +MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65621) +MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33387) +MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79597) +MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33589) +MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47082) +MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25583) +MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18615) +MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24193) +MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 60994) +MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39824) +MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32920) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37956) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23706) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38778) NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71901) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 185776) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 189229) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 252250) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 220615) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 185810) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 189263) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 252318) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 220605) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 60497) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152941) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 166101) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 195828) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 139098) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 105168) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152975) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 166167) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 195938) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 139164) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 105212) NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates_success() (gas: 123604) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 43403) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64752) @@ -370,141 +369,132 @@ NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySet_overrideAllow NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate_success() (gas: 66889) NonceManager_applyPreviousRampsUpdates:test_ZeroInput_success() (gas: 12213) NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9705) -OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5880050) -OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 626160) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 166527) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5872422) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 626094) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 166505) OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 16719) -OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 274713) +OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 274389) OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Success() (gas: 168604) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 181059) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 181037) OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13441) OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 72724) OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15519) -OffRamp_applySourceChainConfigUpdates:test_allowNonOnRampUpdateAfterLaneIsUsed_success() (gas: 285041) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177470) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 333296) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 276562) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 168408) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187974) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 156406) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 545125) -OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10600) -OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92744) -OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63432) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 69993) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 66119) -OffRamp_commit:test_InvalidRootRevert() (gas: 65214) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6641148) -OffRamp_commit:test_NoConfig_Revert() (gas: 6224566) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112985) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121175) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112917) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 355254) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164263) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141269) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 148268) -OffRamp_commit:test_RootWithRMNDisabled_success() (gas: 153986) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 61681) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 232354) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125230) -OffRamp_commit:test_Unhealthy_Revert() (gas: 60482) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206800) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 53621) -OffRamp_constructor:test_Constructor_Success() (gas: 6186663) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136575) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103612) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101461) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 162055) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101378) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101382) -OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17639) -OffRamp_execute:test_LargeBatch_Success() (gas: 3376243) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 371146) -OffRamp_execute:test_MultipleReports_Success() (gas: 298685) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7049316) -OffRamp_execute:test_NoConfig_Revert() (gas: 6273786) -OffRamp_execute:test_NonArray_Revert() (gas: 27680) -OffRamp_execute:test_SingleReport_Success() (gas: 175664) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147820) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6940958) -OffRamp_execute:test_ZeroReports_Revert() (gas: 17361) -OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18533) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 237918) -OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20363) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 198836) -OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48880) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 56102) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 212824) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85495) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 268026) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 91918) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28703) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 15574) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 471595) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48340) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 34145) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28868) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187644) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 197820) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40731) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 404990) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 248696) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 192362) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212388) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 243698) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141476) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 402556) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58286) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73856) +OffRamp_applySourceChainConfigUpdates:test_allowNonOnRampUpdateAfterLaneIsUsed_success() (gas: 284695) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177591) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 333573) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 276839) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 168529) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 188173) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 156527) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 545255) +OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10643) +OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92450) +OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63117) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 69655) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 65803) +OffRamp_commit:test_InvalidRootRevert() (gas: 64898) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6633259) +OffRamp_commit:test_NoConfig_Revert() (gas: 6216677) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112728) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 120561) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112660) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 354785) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 163983) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 140923) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 147631) +OffRamp_commit:test_RootWithRMNDisabled_success() (gas: 153596) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 61365) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 231709) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125027) +OffRamp_commit:test_Unhealthy_Revert() (gas: 60177) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206221) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 53305) +OffRamp_constructor:test_Constructor_Success() (gas: 6179080) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136555) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103592) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101441) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 162036) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101358) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101362) +OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17532) +OffRamp_execute:test_LargeBatch_Success() (gas: 3378447) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 371209) +OffRamp_execute:test_MultipleReports_Success() (gas: 298806) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7041684) +OffRamp_execute:test_NoConfig_Revert() (gas: 6266154) +OffRamp_execute:test_NonArray_Revert() (gas: 27572) +OffRamp_execute:test_SingleReport_Success() (gas: 175631) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147790) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6933352) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17248) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens() (gas: 56213) +OffRamp_executeSingleMessage:test_executeSingleMessage_NonContract() (gas: 20508) +OffRamp_executeSingleMessage:test_executeSingleMessage_NonContractWithTokens() (gas: 238042) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithMessageInterceptor() (gas: 91994) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens() (gas: 268135) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28659) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 15530) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress() (gas: 474650) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48296) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 34101) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28824) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187677) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 197809) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40687) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 405023) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 248786) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 192430) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212456) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 243699) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141510) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 402534) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58242) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73812) OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 574160) OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 522711) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 26839) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 540831) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 540778) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 26795) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 540787) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 540734) OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 451824) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135241) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164880) -OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3888846) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135231) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164892) +OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3905742) OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 121048) -OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89561) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81514) -OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 74194) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 172517) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 213009) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27203) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 165665) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27740) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 55317) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 489426) -OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 314585) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2224654) -OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165207) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 225918) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 226458) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 773856) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 344327) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 37654) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 101487) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 79931) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36812) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 91450) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 37323) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 83562) -OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 156122) -OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 23836) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 62866) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 78418) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 168774) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 170686) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 181914) -OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11509) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14019) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 47579) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 25552) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 213117) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 221794) -OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 289349) -OffRamp_trialExecute:test_trialExecute_Success() (gas: 271823) +OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89737) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81694) +OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 74284) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 172639) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 213251) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27248) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 165935) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27774) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 55362) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 489669) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 314861) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2224794) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165330) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 226161) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 226701) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 774719) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 344726) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 37632) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 101465) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36790) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 91430) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 83518) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens() (gas: 168784) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_RevertWhenInvalidDataLengthReturnData() (gas: 62822) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_RevertWhenPoolDoesNotSupportDest() (gas: 78426) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride() (gas: 170654) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals() (gas: 181893) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11465) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13975) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 47491) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 25464) +OffRamp_trialExecute:test_trialExecute() (gas: 271771) +OffRamp_trialExecute:test_trialExecute_RateLimitError() (gas: 127457) +OffRamp_trialExecute:test_trialExecute_TokenHandlingErrorIsCaught() (gas: 138767) +OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 289412) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 251706) OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17227) OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_Revert() (gas: 67101) @@ -517,32 +507,32 @@ OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Rever OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 98066) OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 93146) OnRamp_constructor:test_Constructor_Success() (gas: 2647459) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115388) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146256) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145831) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144036) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146028) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145426) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140709) -OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38504) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115432) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146300) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145875) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144080) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146072) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145470) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140731) +OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38526) OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143112) -OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36589) +OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36611) OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36493) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 18290) OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 38412) OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 23629) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186583) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 213012) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147026) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 161215) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3919758) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186715) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 213144) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147070) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 161303) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3963792) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 24015) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75832) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75854) OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38588) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 281474) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 281529) OnRamp_getFee:test_EmptyMessage_Success() (gas: 98692) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 65453) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87185) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 65475) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87119) OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 35166) OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113865) OnRamp_getFee:test_Unhealthy_Revert() (gas: 17040) @@ -555,11 +545,11 @@ OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() (g OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() (gas: 13264) OnRamp_setDynamicConfig:test_setDynamicConfig_Success() (gas: 56440) OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 125901) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 172858) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 172880) PingPong_setOutOfOrderExecution:test_OutOfOrderExecution_Success() (gas: 20283) PingPong_setPaused:test_Pausing_Success() (gas: 17738) -PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 151971) -PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 177586) +PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 151993) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 177608) RMNHome_getConfigDigests:test_getConfigDigests_success() (gas: 1079685) RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() (gas: 23879) RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() (gas: 10597) @@ -582,27 +572,27 @@ RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_Dupli RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_NotEnoughObservers_reverts() (gas: 21405) RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_OutOfBoundsNodesLength_reverts() (gas: 137318) RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_OutOfBoundsObserverNodeIndex_reverts() (gas: 20522) -RMNRemote_constructor:test_constructor_success() (gas: 8334) -RMNRemote_constructor:test_constructor_zeroChainSelector_reverts() (gas: 59184) -RMNRemote_curse:test_curse_AlreadyCursed_duplicateSubject_reverts() (gas: 154479) -RMNRemote_curse:test_curse_calledByNonOwner_reverts() (gas: 18712) -RMNRemote_curse:test_curse_success() (gas: 149431) -RMNRemote_global_and_legacy_curses:test_global_and_legacy_curses_success() (gas: 133512) +RMNRemote_constructor:test_constructor() (gas: 8398) +RMNRemote_curse:test_curse_AlreadyCursed_duplicateSubject_reverts() (gas: 154501) +RMNRemote_curse:test_curse_calledByNonOwner_reverts() (gas: 18734) +RMNRemote_curse:test_curse_success() (gas: 149475) +RMNRemote_global_and_legacy_curses:test_global_and_legacy_curses_success() (gas: 133441) +RMNRemote_isBlessed:test_isBlessed() (gas: 17588) RMNRemote_setConfig:test_setConfig_ZeroValueNotAllowed_revert() (gas: 37971) RMNRemote_setConfig:test_setConfig_addSigner_removeSigner_success() (gas: 993448) RMNRemote_setConfig:test_setConfig_duplicateOnChainPublicKey_reverts() (gas: 323540) RMNRemote_setConfig:test_setConfig_invalidSignerOrder_reverts() (gas: 80201) RMNRemote_setConfig:test_setConfig_notEnoughSigners_reverts() (gas: 54232) -RMNRemote_uncurse:test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() (gas: 51993) -RMNRemote_uncurse:test_uncurse_calledByNonOwner_reverts() (gas: 18682) -RMNRemote_uncurse:test_uncurse_success() (gas: 40171) -RMNRemote_verify_withConfigNotSet:test_verify_reverts() (gas: 13578) -RMNRemote_verify_withConfigSet:test_verify_InvalidSignature_reverts() (gas: 96449) -RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_duplicateSignature_reverts() (gas: 94267) -RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_not_sorted_reverts() (gas: 101330) -RMNRemote_verify_withConfigSet:test_verify_ThresholdNotMet_reverts() (gas: 304634) -RMNRemote_verify_withConfigSet:test_verify_UnexpectedSigner_reverts() (gas: 428126) -RMNRemote_verify_withConfigSet:test_verify_success() (gas: 86159) +RMNRemote_uncurse:test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() (gas: 51940) +RMNRemote_uncurse:test_uncurse_calledByNonOwner_reverts() (gas: 18615) +RMNRemote_uncurse:test_uncurse_success() (gas: 40135) +RMNRemote_verify_withConfigNotSet:test_verify_reverts() (gas: 13600) +RMNRemote_verify_withConfigSet:test_verify_InvalidSignature_reverts() (gas: 96471) +RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_duplicateSignature_reverts() (gas: 94289) +RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_not_sorted_reverts() (gas: 101352) +RMNRemote_verify_withConfigSet:test_verify_ThresholdNotMet_reverts() (gas: 304744) +RMNRemote_verify_withConfigSet:test_verify_UnexpectedSigner_reverts() (gas: 428284) +RMNRemote_verify_withConfigSet:test_verify_success() (gas: 86181) RateLimiter_constructor:test_Constructor_Success() (gas: 19806) RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16042) RateLimiter_consume:test_AggregateValueRateLimitReached_Revert() (gas: 22435) @@ -628,20 +618,20 @@ Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89591) Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10750087) Router_applyRampUpdates:test_OnRampDisable() (gas: 56445) Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12414) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 131425) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 221699) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 131447) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 221710) Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 71858) Router_ccipSend:test_InvalidMsgValue() (gas: 32411) Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 69524) -Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 193296) +Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 193318) Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 61550) -Router_ccipSend:test_NativeFeeToken_Success() (gas: 191900) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 226539) +Router_ccipSend:test_NativeFeeToken_Success() (gas: 191922) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 226583) Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 25056) Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 45056) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 194209) -Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 140674) -Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 230883) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 194231) +Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 140696) +Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 230894) Router_constructor:test_Constructor_Success() (gas: 13222) Router_getArmProxy:test_getArmProxy() (gas: 10573) Router_getFee:test_GetFeeSupportedChain_Success() (gas: 51934) @@ -681,63 +671,65 @@ TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 3 TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18202) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49592) TokenPoolFactory_constructor:test_constructor_Revert() (gas: 1121653) -TokenPoolFactory_createTokenPool:test_createTokenPoolLockRelease_ExistingToken_predict_Success() (gas: 12293466) -TokenPoolFactory_createTokenPool:test_createTokenPool_BurnFromMintTokenPool_Success() (gas: 6290905) -TokenPoolFactory_createTokenPool:test_createTokenPool_ExistingRemoteToken_AndPredictPool_Success() (gas: 13043750) -TokenPoolFactory_createTokenPool:test_createTokenPool_RemoteTokenHasDifferentDecimals_Success() (gas: 13051052) -TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingRemoteContracts_predict_Success() (gas: 13380456) -TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingTokenOnRemoteChain_Success() (gas: 6075765) -TokenPoolFactory_createTokenPool:test_createTokenPool_WithRemoteTokenAndRemotePool_Success() (gas: 6287377) -TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2688992) -TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12141) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23589) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 178451) +TokenPoolFactory_createTokenPool:test_createTokenPoolLockRelease_ExistingToken_predict_Success() (gas: 12386310) +TokenPoolFactory_createTokenPool:test_createTokenPool_BurnFromMintTokenPool_Success() (gas: 6364709) +TokenPoolFactory_createTokenPool:test_createTokenPool_ExistingRemoteToken_AndPredictPool_Success() (gas: 13167390) +TokenPoolFactory_createTokenPool:test_createTokenPool_RemoteTokenHasDifferentDecimals_Success() (gas: 13174692) +TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingRemoteContracts_predict_Success() (gas: 13504109) +TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingTokenOnRemoteChain_Success() (gas: 6150583) +TokenPoolFactory_createTokenPool:test_createTokenPool_WithRemoteTokenAndRemotePool_Success() (gas: 6361166) +TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2717776) +TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12119) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23567) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 178398) TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23929) TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8408) TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 25005) TokenPoolWithAllowList_setRouter:test_ZeroAddressNotAllowed_Revert() (gas: 10729) -TokenPool_addRemotePool:test_NonExistentChain_Revert() (gas: 14311) -TokenPool_addRemotePool:test_PoolAlreadyAdded_Revert() (gas: 117249) -TokenPool_addRemotePool:test_ZeroLengthAddressNotAllowed_Revert() (gas: 14036) -TokenPool_addRemotePool:test_addRemotePool_Success() (gas: 157117) +TokenPool_addRemotePool:test_NonExistentChain_Revert() (gas: 14222) +TokenPool_addRemotePool:test_PoolAlreadyAdded_Revert() (gas: 117205) +TokenPool_addRemotePool:test_ZeroLengthAddressNotAllowed_Revert() (gas: 14014) +TokenPool_addRemotePool:test_addRemotePool_MultipleActive() (gas: 472820) +TokenPool_addRemotePool:test_addRemotePool_Success() (gas: 157095) TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 455575) -TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 15054) -TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11885) -TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 592195) -TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 226494) -TokenPool_calculateLocalAmount:test_calculateLocalAmount() (gas: 84730) -TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 71410) -TokenPool_constructor:test_immutableFields_Success() (gas: 21946) +TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 15032) +TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11863) +TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 592089) +TokenPool_applyChainUpdates:test_applyChainUpdates_UpdatesRemotePoolHashes() (gas: 1077776) +TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 226472) +TokenPool_calculateLocalAmount:test_calculateLocalAmount() (gas: 93680) +TokenPool_constructor:test_constructor() (gas: 21930) +TokenPool_constructor:test_constructor_DecimalCallFails() (gas: 2714089) TokenPool_getRemotePool:test_getRemotePools() (gas: 330500) -TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 21526) -TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 240488) -TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 94313) -TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 21090) -TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 204288) -TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 49172) -TokenPool_parseRemoteDecimals:test_parseRemoteDecimals() (gas: 14086) -TokenPool_parseRemoteDecimals:test_parseRemoteDecimals_NoDecimalsDefaultsToLocalDecimals() (gas: 9771) +TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 21504) +TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 240435) +TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 94291) +TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 21156) +TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 204376) +TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 49238) +TokenPool_parseRemoteDecimals:test_parseRemoteDecimals() (gas: 14020) +TokenPool_parseRemoteDecimals:test_parseRemoteDecimals_NoDecimalsDefaultsToLocalDecimals() (gas: 9727) TokenPool_removeRemotePool:test_InvalidRemotePoolForChain_Revert() (gas: 17499) TokenPool_removeRemotePool:test_NonExistentChain_Revert() (gas: 14344) -TokenPool_removeRemotePool:test_removeRemotePool_Success() (gas: 188431) +TokenPool_removeRemotePool:test_removeRemotePool_Success() (gas: 188387) TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17214) TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15307) -TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11024) -TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 37672) -USDCBridgeMigrator_BurnLockedUSDC:test_PrimaryMechanism_Success() (gas: 136004) -USDCBridgeMigrator_BurnLockedUSDC:test_WhileMigrationPause_Revert() (gas: 109849) +TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11002) +TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 37606) +USDCBridgeMigrator_BurnLockedUSDC:test_PrimaryMechanism_Success() (gas: 135869) +USDCBridgeMigrator_BurnLockedUSDC:test_WhileMigrationPause_Revert() (gas: 109729) USDCBridgeMigrator_BurnLockedUSDC:test_invalidPermissions_Revert() (gas: 39493) -USDCBridgeMigrator_BurnLockedUSDC:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 310057) -USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_Success() (gas: 147035) -USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209377) +USDCBridgeMigrator_BurnLockedUSDC:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 309798) +USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_Success() (gas: 146939) +USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209089) USDCBridgeMigrator_cancelMigrationProposal:test_cancelExistingCCTPMigrationProposal_Success() (gas: 56155) USDCBridgeMigrator_cancelMigrationProposal:test_cannotCancelANonExistentMigrationProposal_Revert() (gas: 12669) USDCBridgeMigrator_excludeTokensFromBurn:test_excludeTokensWhenNoMigrationProposalPending_Revert() (gas: 13579) USDCBridgeMigrator_proposeMigration:test_ChainNotUsingLockRelease_Revert() (gas: 15765) USDCBridgeMigrator_provideLiquidity:test_PrimaryMechanism_Success() (gas: 135986) USDCBridgeMigrator_provideLiquidity:test_WhileMigrationPause_Revert() (gas: 109871) -USDCBridgeMigrator_provideLiquidity:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13379) -USDCBridgeMigrator_provideLiquidity:test_cannotProvideLiquidityWhenMigrationProposalPending_Revert() (gas: 67417) +USDCBridgeMigrator_provideLiquidity:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13390) +USDCBridgeMigrator_provideLiquidity:test_cannotProvideLiquidityWhenMigrationProposalPending_Revert() (gas: 67428) USDCBridgeMigrator_provideLiquidity:test_cannotProvideLiquidity_AfterMigration_Revert() (gas: 313898) USDCBridgeMigrator_provideLiquidity:test_invalidPermissions_Revert() (gas: 39493) USDCBridgeMigrator_provideLiquidity:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 310057) @@ -756,13 +748,13 @@ USDCBridgeMigrator_updateChainSelectorMechanism:test_lockOrBurn_then_BurnInCCTPM USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_Success() (gas: 147035) USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209448) USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 26049) -USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35369) -USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29947) -USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133581) -USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 433813) -USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 265825) +USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35297) +USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29875) +USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133408) +USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 433408) +USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 265695) USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 47231) -USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 95315) +USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 95262) USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66437) USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11314) USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10107) \ No newline at end of file diff --git a/contracts/gas-snapshots/liquiditymanager.gas-snapshot b/contracts/gas-snapshots/liquiditymanager.gas-snapshot index bdbfc60452b..2e2d0962186 100644 --- a/contracts/gas-snapshots/liquiditymanager.gas-snapshot +++ b/contracts/gas-snapshots/liquiditymanager.gas-snapshot @@ -3,9 +3,9 @@ LiquidityManager_addLiquidity:test_addLiquiditySuccess() (gas: 279198) LiquidityManager_rebalanceLiquidity:test_InsufficientLiquidityReverts() (gas: 206764) LiquidityManager_rebalanceLiquidity:test_InvalidRemoteChainReverts() (gas: 192374) LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess() (gas: 9141798) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 9246772) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 9241912) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 9169653) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 9306766) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 9301906) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 9231739) LiquidityManager_rebalanceLiquidity:test_rebalanceLiquiditySuccess() (gas: 382928) LiquidityManager_receive:test_receive_success() (gas: 21182) LiquidityManager_removeLiquidity:test_InsufficientLiquidityReverts() (gas: 184959) @@ -19,7 +19,7 @@ LiquidityManager_setFinanceRole:test_OnlyOwnerReverts() (gas: 10987) LiquidityManager_setFinanceRole:test_setFinanceRoleSuccess() (gas: 21836) LiquidityManager_setLocalLiquidityContainer:test_OnlyOwnerReverts() (gas: 11030) LiquidityManager_setLocalLiquidityContainer:test_ReverstWhen_CalledWithTheZeroAddress() (gas: 10621) -LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3784709) +LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3847203) LiquidityManager_setMinimumLiquidity:test_OnlyOwnerReverts() (gas: 10925) LiquidityManager_setMinimumLiquidity:test_setMinimumLiquiditySuccess() (gas: 36389) LiquidityManager_withdrawERC20:test_withdrawERC20Reverts() (gas: 180396) diff --git a/contracts/scripts/lcov_prune b/contracts/scripts/lcov_prune index 0f16715cb2e..9d5d592c646 100755 --- a/contracts/scripts/lcov_prune +++ b/contracts/scripts/lcov_prune @@ -30,7 +30,7 @@ exclusion_list_ccip=( "src/v0.8/ConfirmedOwnerWithProposal.sol" "src/v0.8/tests/MockV3Aggregator.sol" "src/v0.8/ccip/applications/CCIPClientExample.sol" - "src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol" + "src/v0.8/keystone/*" ) exclusion_list_shared=( diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol index d8a04e359b1..58261eff499 100644 --- a/contracts/src/v0.8/ccip/FeeQuoter.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -15,6 +15,7 @@ import {Internal} from "./libraries/Internal.sol"; import {Pool} from "./libraries/Pool.sol"; import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; +import {IERC165} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol"; import {EnumerableSet} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; /// @notice The FeeQuoter contract responsibility is to: @@ -493,6 +494,14 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, } } + /// @notice Signals which version of the pool interface is supported + function supportsInterface( + bytes4 interfaceId + ) public pure override returns (bool) { + return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IFeeQuoter).interfaceId + || interfaceId == type(ITypeAndVersion).interfaceId || interfaceId == type(IERC165).interfaceId; + } + /// @inheritdoc IReceiver /// @notice Handles the report containing price feeds and updates the internal price storage. /// @dev This function is called to process incoming price feed data. diff --git a/contracts/src/v0.8/ccip/capability/CCIPHome.sol b/contracts/src/v0.8/ccip/capability/CCIPHome.sol index 7a425566c33..e43e4b0d03f 100644 --- a/contracts/src/v0.8/ccip/capability/CCIPHome.sol +++ b/contracts/src/v0.8/ccip/capability/CCIPHome.sol @@ -62,7 +62,7 @@ import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts /// │ Active │ revokeCandidate │ Candidate │◄───────────┐ /// │ [1,0] │◄───────────────────┤ [1,1] │────────────┘ /// │ ├───────────────────►│ │ -/// └─────────────┘ setSecondary └─────────────┘ +/// └─────────────┘ setCandidate └─────────────┘ /// contract CCIPHome is Ownable2StepMsgSender, ITypeAndVersion, ICapabilityConfiguration, IERC165 { using EnumerableSet for EnumerableSet.UintSet; diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index 5f2f8a6c472..f5bcdd434f7 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -224,7 +224,7 @@ library Internal { // be relied upon by the destination pool to validate the source pool. bytes sourcePoolAddress; address destTokenAddress; // ─╮ Address of destination token - uint32 destGasAmount; //──────╯ The amount of gas available for the releaseOrMint and transfer calls on the offRamp. + uint32 destGasAmount; // ─────╯ The amount of gas available for the releaseOrMint and transfer calls on the offRamp. // Optional pool data to be transferred to the destination chain. Be default this is capped at // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead // has to be set for the specific token. diff --git a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol index 5d8cc7f69d1..b6741f78fbe 100644 --- a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol +++ b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol @@ -101,7 +101,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, Ownable2StepMsgSender { /// @notice Constant length component for transmit functions with no signatures. /// The signatures are expected to match transmitPlugin(reportContext, report). uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT_NO_SIGNATURES = 4 // function selector. - + 3 * 32 // 3 words containing reportContext. + + 2 * 32 // 2 words containing reportContext. + 32 // word containing start location of abiencoded report value. + 32; // word containing length of report. @@ -230,7 +230,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, Ownable2StepMsgSender { uint8 ocrPluginType, // NOTE: If these parameters are changed, expectedMsgDataLength and/or TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT // need to be changed accordingly. - bytes32[3] calldata reportContext, + bytes32[2] calldata reportContext, bytes calldata report, bytes32[] memory rs, bytes32[] memory ss, @@ -239,7 +239,6 @@ abstract contract MultiOCR3Base is ITypeAndVersion, Ownable2StepMsgSender { // reportContext consists of: // reportContext[0]: ConfigDigest. // reportContext[1]: 24 byte padding, 8 byte sequence number. - // reportContext[2]: ExtraHash. ConfigInfo memory configInfo = s_ocrConfigs[ocrPluginType].configInfo; bytes32 configDigest = reportContext[0]; diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 80873175039..d276ce26a96 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -48,7 +48,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { error InvalidRoot(); error CanOnlySelfCall(); error ReceiverError(bytes err); - error TokenHandlingError(bytes err); + error TokenHandlingError(address target, bytes err); error ReleaseOrMintBalanceMismatch(uint256 amountReleased, uint256 balancePre, uint256 balancePost); error EmptyReport(uint64 sourceChainSelector); error EmptyBatch(); @@ -322,7 +322,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @notice Transmit function for execution reports. The function takes no signatures, and expects the exec plugin /// type to be configured with no signatures. /// @param report serialized execution report. - function execute(bytes32[3] calldata reportContext, bytes calldata report) external { + function execute(bytes32[2] calldata reportContext, bytes calldata report) external { _batchExecute(abi.decode(report, (Internal.ExecutionReport[])), new GasLimitOverride[][](0)); bytes32[] memory emptySigs = new bytes32[](0); @@ -670,7 +670,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { ); // Wrap and rethrow the error so we can catch it lower in the stack. - if (!success) revert TokenHandlingError(returnData); + if (!success) revert TokenHandlingError(localPoolAddress, returnData); // If the call was successful, the returnData should be the amount released or minted denominated in the local // token's decimals. @@ -711,7 +711,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { Internal.GAS_FOR_CALL_EXACT_CHECK, Internal.MAX_RET_BYTES ); - if (!success) revert TokenHandlingError(returnData); + if (!success) revert TokenHandlingError(token, returnData); // If the call was successful, the returnData should contain only the balance. if (returnData.length != Internal.MAX_BALANCE_OF_RET_BYTES) { @@ -773,7 +773,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// price updates is submitted, we are OK to revert to preserve the invariant that we always revert on invalid /// sequence number ranges. If that happens, prices will be updated in later rounds. function commit( - bytes32[3] calldata reportContext, + bytes32[2] calldata reportContext, bytes calldata report, bytes32[] calldata rs, bytes32[] calldata ss, diff --git a/contracts/src/v0.8/ccip/pools/TokenPool.sol b/contracts/src/v0.8/ccip/pools/TokenPool.sol index be8cc1ee7a3..69bab031f57 100644 --- a/contracts/src/v0.8/ccip/pools/TokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/TokenPool.sol @@ -10,6 +10,8 @@ import {Pool} from "../libraries/Pool.sol"; import {RateLimiter} from "../libraries/RateLimiter.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata} from + "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; @@ -17,18 +19,19 @@ import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts /// A token pool serves as isolated place for holding tokens and token specific logic /// that may execute as tokens move across the bridge. /// @dev This pool supports different decimals on different chains but using this feature could impact the total number -/// of tokens in circulation. Since all of the tokens are burned on the source, and a rounded amount is minted on the -/// destination, the number of tokens minted could be less than the number of tokens burned. This is because the source -/// chain does not know about the destination token decimals. This is not a problem if the decimals are the same on both -/// chains. +/// of tokens in circulation. Since all of the tokens are locked/burned on the source, and a rounded amount is +/// minted/released on the destination, the number of tokens minted/released could be less than the number of tokens +/// burned/locked. This is because the source chain does not know about the destination token decimals. This is not a +/// problem if the decimals are the same on both chains. /// /// Example: /// Assume there is a token with 6 decimals on chain A and 3 decimals on chain B. -/// - 1.123456 tokens are burned on chain A. +/// - 1.234567 tokens are burned on chain A. /// - 1.234 tokens are minted on chain B. /// When sending the 1.234 tokens back to chain A, you will receive 1.234000 tokens on chain A, effectively losing -/// 0.000456 tokens. In the case of a burnMint pool, these funds are burned. In the case of a lockRelease pool, these -/// funds accumulate in the pool on chain A. +/// 0.000567 tokens. +/// In the case of a burnMint pool on chain A, these funds are burned in the pool on chain A. +/// In the case of a lockRelease pool on chain A, these funds accumulate in the pool on chain A. abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableSet for EnumerableSet.AddressSet; @@ -49,6 +52,8 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { error PoolAlreadyAdded(uint64 remoteChainSelector, bytes remotePoolAddress); error InvalidRemotePoolForChain(uint64 remoteChainSelector, bytes remotePoolAddress); error InvalidRemoteChainDecimals(bytes sourcePoolData); + error OverflowDetected(uint8 remoteDecimals, uint8 localDecimals, uint256 remoteAmount); + error InvalidDecimalArgs(uint8 expected, uint8 actual); event Locked(address indexed sender, uint256 amount); event Burned(address indexed sender, uint256 amount); @@ -119,7 +124,17 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { if (address(token) == address(0) || router == address(0) || rmnProxy == address(0)) revert ZeroAddressNotAllowed(); i_token = token; i_rmnProxy = rmnProxy; + + try IERC20Metadata(address(token)).decimals() returns (uint8 actualTokenDecimals) { + if (localTokenDecimals != actualTokenDecimals) { + revert InvalidDecimalArgs(localTokenDecimals, actualTokenDecimals); + } + } catch { + // The decimals function doesn't exist, which is possible since it's optional in the ERC20 spec. We skip the check and + // assume the supplied token decimals are correct. + } i_tokenDecimals = localTokenDecimals; + s_router = IRouter(router); // Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas. @@ -256,18 +271,33 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { /// @param remoteAmount The amount on the remote chain. /// @param remoteDecimals The decimals of the token on the remote chain. /// @return The local amount. - /// @dev This function assumes the inputs don't overflow and does no checks to avoid this. For any normal inputs, this - /// should not be a problem. The only way to overflow is when the given arguments cannot be represented in the uint256 - /// type, which means the inputs are invalid. + /// @dev This function protects against overflows. If there is a transaction that hits the overflow check, it is + /// probably incorrect as that means the amount cannot be represented on this chain. If the local decimals have been + /// wrongly configured, the token issuer could redeploy the pool with the correct decimals and manually re-execute the + /// CCIP tx to fix the issue. function _calculateLocalAmount(uint256 remoteAmount, uint8 remoteDecimals) internal view virtual returns (uint256) { if (remoteDecimals == i_tokenDecimals) { return remoteAmount; } if (remoteDecimals > i_tokenDecimals) { + uint8 decimalsDiff = remoteDecimals - i_tokenDecimals; + if (decimalsDiff > 77) { + // This is a safety check to prevent overflow in the next calculation. + revert OverflowDetected(remoteDecimals, i_tokenDecimals, remoteAmount); + } // Solidity rounds down so there is no risk of minting more tokens than the remote chain sent. - return remoteAmount / (10 ** (remoteDecimals - i_tokenDecimals)); + return remoteAmount / (10 ** decimalsDiff); + } + + // This is a safety check to prevent overflow in the next calculation. + // More than 77 would never fit in a uint256 and would cause an overflow. We also check if the resulting amount + // would overflow. + uint8 diffDecimals = i_tokenDecimals - remoteDecimals; + if (diffDecimals > 77 || remoteAmount > type(uint256).max / (10 ** diffDecimals)) { + revert OverflowDetected(remoteDecimals, i_tokenDecimals, remoteAmount); } - return remoteAmount * (10 ** (i_tokenDecimals - remoteDecimals)); + + return remoteAmount * (10 ** diffDecimals); } // ================================================================ diff --git a/contracts/src/v0.8/ccip/rmn/RMNHome.sol b/contracts/src/v0.8/ccip/rmn/RMNHome.sol index 684dc3e994e..92aab25ae8e 100644 --- a/contracts/src/v0.8/ccip/rmn/RMNHome.sol +++ b/contracts/src/v0.8/ccip/rmn/RMNHome.sol @@ -54,7 +54,7 @@ import {Ownable2StepMsgSender} from "../../shared/access/Ownable2StepMsgSender.s /// │ Active │ revokeCandidate │ Candidate │◄───────────┐ /// │ [1,0] │◄───────────────────┤ [1,1] │────────────┘ /// │ ├───────────────────►│ │ -/// └─────────────┘ setSecondary └─────────────┘ +/// └─────────────┘ setCandidate └─────────────┘ /// contract RMNHome is Ownable2StepMsgSender, ITypeAndVersion { event ConfigSet(bytes32 indexed configDigest, uint32 version, StaticConfig staticConfig, DynamicConfig dynamicConfig); diff --git a/contracts/src/v0.8/ccip/rmn/RMNRemote.sol b/contracts/src/v0.8/ccip/rmn/RMNRemote.sol index 5faa1d720e7..4e7ce766443 100644 --- a/contracts/src/v0.8/ccip/rmn/RMNRemote.sol +++ b/contracts/src/v0.8/ccip/rmn/RMNRemote.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IRMN} from "../interfaces/IRMN.sol"; import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; import {Ownable2StepMsgSender} from "../../shared/access/Ownable2StepMsgSender.sol"; @@ -19,7 +20,10 @@ bytes16 constant LEGACY_CURSE_SUBJECT = 0x01000000000000000000000000000000; bytes16 constant GLOBAL_CURSE_SUBJECT = 0x01000000000000000000000000000001; /// @notice This contract supports verification of RMN reports for any Any2EVM OffRamp. -contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote { +/// @dev This contract implements both the new IRMNRemote interface and the legacy IRMN interface. This is to allow for +/// a seamless migration from the legacy RMN contract to this one. The only function that has been dropped in the newer +/// interface is `isBlessed`. For the `isBlessed` function, this contract relays the call to the legacy RMN contract. +contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote, IRMN { using EnumerableSet for EnumerableSet.Bytes16Set; error AlreadyCursed(bytes16 subject); @@ -33,6 +37,7 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote { error ThresholdNotMet(); error UnexpectedSigner(); error ZeroValueNotAllowed(); + error IsBlessedNotAvailable(); event ConfigSet(uint32 indexed version, Config config); event Cursed(bytes16[] subjects); @@ -67,6 +72,7 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote { string public constant override typeAndVersion = "RMNRemote 1.6.0-dev"; uint64 internal immutable i_localChainSelector; + IRMN internal immutable i_legacyRMN; Config private s_config; uint32 private s_configCount; @@ -80,11 +86,11 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote { mapping(address signer => bool exists) private s_signers; // for more gas efficient verify. /// @param localChainSelector the chain selector of the chain this contract is deployed to. - constructor( - uint64 localChainSelector - ) { + constructor(uint64 localChainSelector, IRMN legacyRMN) { if (localChainSelector == 0) revert ZeroValueNotAllowed(); i_localChainSelector = localChainSelector; + + i_legacyRMN = legacyRMN; } // ================================================================ @@ -248,7 +254,7 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote { } /// @inheritdoc IRMNRemote - function isCursed() external view returns (bool) { + function isCursed() external view override(IRMN, IRMNRemote) returns (bool) { // There are zero curses under normal circumstances, which means it's cheaper to check for the absence of curses. // than to check the subject list twice, as we have to check for both the legacy and global curse subjects. if (s_cursedSubjects.length() == 0) { @@ -260,7 +266,7 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote { /// @inheritdoc IRMNRemote function isCursed( bytes16 subject - ) external view returns (bool) { + ) external view override(IRMN, IRMNRemote) returns (bool) { // There are zero curses under normal circumstances, which means it's cheaper to check for the absence of curses. // than to check the subject list twice, as we have to check for both the given and global curse subjects. if (s_cursedSubjects.length() == 0) { @@ -268,4 +274,20 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote { } return s_cursedSubjects.contains(subject) || s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); } + + // ================================================================ + // │ Legacy pass through │ + // ================================================================ + + /// @inheritdoc IRMN + /// @dev This function is only expected to be used for messages from CCIP versions below 1.6. + function isBlessed( + TaggedRoot calldata taggedRoot + ) external view returns (bool) { + if (i_legacyRMN == IRMN(address(0))) { + revert IsBlessedNotAvailable(); + } + + return i_legacyRMN.isBlessed(taggedRoot); + } } diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol index aba4e178865..ebd800b7d48 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol @@ -2,30 +2,42 @@ pragma solidity 0.8.24; import {KeystoneFeedsPermissionHandler} from "../../../keystone/KeystoneFeedsPermissionHandler.sol"; + +import {KeystoneForwarder} from "../../../keystone/KeystoneForwarder.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_onReport is FeeQuoterSetup { - address internal constant FORWARDER_1 = address(0x1); - address internal constant WORKFLOW_OWNER_1 = address(0x3); - bytes10 internal constant WORKFLOW_NAME_1 = "workflow1"; - bytes2 internal constant REPORT_NAME_1 = "01"; + bytes32 internal constant EXECUTION_ID = hex"6d795f657865637574696f6e5f69640000000000000000000000000000000000"; + address internal constant TRANSMITTER = address(50); + bytes32 internal constant WORKFLOW_ID_1 = hex"6d795f6964000000000000000000000000000000000000000000000000000000"; + address internal constant WORKFLOW_OWNER_1 = address(51); + bytes10 internal constant WORKFLOW_NAME_1 = hex"000000000000DEADBEEF"; + bytes2 internal constant REPORT_NAME_1 = hex"0001"; address internal s_onReportTestToken1; address internal s_onReportTestToken2; + bytes public encodedPermissionsMetadata; + KeystoneForwarder internal s_forwarder; function setUp() public virtual override { super.setUp(); + + s_forwarder = new KeystoneForwarder(); + s_onReportTestToken1 = s_sourceTokens[0]; s_onReportTestToken2 = _deploySourceToken("onReportTestToken2", 0, 20); KeystoneFeedsPermissionHandler.Permission[] memory permissions = new KeystoneFeedsPermissionHandler.Permission[](1); permissions[0] = KeystoneFeedsPermissionHandler.Permission({ - forwarder: FORWARDER_1, + forwarder: address(s_forwarder), workflowOwner: WORKFLOW_OWNER_1, workflowName: WORKFLOW_NAME_1, reportName: REPORT_NAME_1, isAllowed: true }); + + encodedPermissionsMetadata = abi.encodePacked(WORKFLOW_ID_1, WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeeds = new FeeQuoter.TokenPriceFeedUpdate[](2); tokenPriceFeeds[0] = FeeQuoter.TokenPriceFeedUpdate({ sourceToken: s_onReportTestToken1, @@ -39,10 +51,7 @@ contract FeeQuoter_onReport is FeeQuoterSetup { s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeeds); } - function test_onReport_Success() public { - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - + function test_onReport() public { FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](2); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); @@ -56,7 +65,7 @@ contract FeeQuoter_onReport is FeeQuoterSetup { vm.expectEmit(); emit FeeQuoter.UsdPerTokenUpdated(s_onReportTestToken2, expectedStoredToken2Price, block.timestamp); - changePrank(FORWARDER_1); + changePrank(address(s_forwarder)); s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); vm.assertEq(s_feeQuoter.getTokenPrice(report[0].token).value, expectedStoredToken1Price); @@ -66,11 +75,34 @@ contract FeeQuoter_onReport is FeeQuoterSetup { vm.assertEq(s_feeQuoter.getTokenPrice(report[1].token).timestamp, report[1].timestamp); } - function test_OnReport_StaleUpdate_SkipPriceUpdate_Success() public { - //Creating a correct report - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + function test_onReport_withKeystoneForwarderContract() public { + FeeQuoter.ReceivedCCIPFeedReport[] memory priceReportRaw = new FeeQuoter.ReceivedCCIPFeedReport[](2); + priceReportRaw[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: s_onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); + priceReportRaw[1] = + FeeQuoter.ReceivedCCIPFeedReport({token: s_onReportTestToken2, price: 4e18, timestamp: uint32(block.timestamp)}); + + uint224 expectedStoredToken1Price = s_feeQuoter.calculateRebasedValue(18, 18, priceReportRaw[0].price); + uint224 expectedStoredToken2Price = s_feeQuoter.calculateRebasedValue(18, 20, priceReportRaw[1].price); + + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(s_onReportTestToken1, expectedStoredToken1Price, block.timestamp); + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(s_onReportTestToken2, expectedStoredToken2Price, block.timestamp); + changePrank(address(s_forwarder)); + s_forwarder.route( + EXECUTION_ID, TRANSMITTER, address(s_feeQuoter), encodedPermissionsMetadata, abi.encode(priceReportRaw) + ); + + vm.assertEq(s_feeQuoter.getTokenPrice(priceReportRaw[0].token).value, expectedStoredToken1Price); + vm.assertEq(s_feeQuoter.getTokenPrice(priceReportRaw[0].token).timestamp, priceReportRaw[0].timestamp); + + vm.assertEq(s_feeQuoter.getTokenPrice(priceReportRaw[1].token).value, expectedStoredToken2Price); + vm.assertEq(s_feeQuoter.getTokenPrice(priceReportRaw[1].token).timestamp, priceReportRaw[1].timestamp); + } + + function test_OnReport_SkipPriceUpdateWhenStaleUpdateReceived() public { FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); @@ -80,7 +112,7 @@ contract FeeQuoter_onReport is FeeQuoterSetup { vm.expectEmit(); emit FeeQuoter.UsdPerTokenUpdated(s_onReportTestToken1, expectedStoredTokenPrice, block.timestamp); - changePrank(FORWARDER_1); + changePrank(address(s_forwarder)); //setting the correct price and time with the correct report s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); @@ -100,22 +132,18 @@ contract FeeQuoter_onReport is FeeQuoterSetup { assertEq(vm.getRecordedLogs().length, 0); } - function test_onReport_TokenNotSupported_Revert() public { - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + function test_onReport_RevertWhen_TokenNotSupported() public { FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[1], price: 4e18, timestamp: uint32(block.timestamp)}); // Revert due to token config not being set with the isEnabled flag vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, s_sourceTokens[1])); - vm.startPrank(FORWARDER_1); + changePrank(address(s_forwarder)); s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); } - function test_onReport_InvalidForwarder_Reverts() public { - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + function test_onReport_RevertWhen_InvalidForwarder() public { FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[0], price: 4e18, timestamp: uint32(block.timestamp)}); @@ -132,16 +160,4 @@ contract FeeQuoter_onReport is FeeQuoterSetup { changePrank(STRANGER); s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); } - - function test_onReport_UnsupportedToken_Reverts() public { - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); - report[0] = - FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[1], price: 4e18, timestamp: uint32(block.timestamp)}); - - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, s_sourceTokens[1])); - changePrank(FORWARDER_1); - s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); - } } diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol new file mode 100644 index 00000000000..a9352392301 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IReceiver} from "../../../keystone/interfaces/IReceiver.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol"; +import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; +import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; + +contract FeeQuoter_supportsInterface is FeeQuoterSetup { + function test_SupportsInterface_Success() public view { + assertTrue(s_feeQuoter.supportsInterface(type(IReceiver).interfaceId)); + assertTrue(s_feeQuoter.supportsInterface(type(ITypeAndVersion).interfaceId)); + assertTrue(s_feeQuoter.supportsInterface(type(IFeeQuoter).interfaceId)); + assertTrue(s_feeQuoter.supportsInterface(type(IERC165).interfaceId)); + } +} diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol index 38838f6acb2..d3567c6027d 100644 --- a/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol +++ b/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol @@ -10,6 +10,7 @@ contract CCIPReaderTester { mapping(uint64 sourceChainSelector => OffRamp.SourceChainConfig sourceChainConfig) internal s_sourceChainConfigs; mapping(uint64 destChainSelector => uint64 sequenceNumber) internal s_destChainSeqNrs; mapping(uint64 sourceChainSelector => mapping(bytes sender => uint64 nonce)) internal s_senderNonce; + uint64 private s_latestPriceSequenceNumber; /// @notice Gets the next sequence number to be used in the onRamp /// @param destChainSelector The destination chain selector @@ -52,6 +53,19 @@ contract CCIPReaderTester { s_sourceChainConfigs[sourceChainSelector] = sourceChainConfig; } + /// @notice sets the sequence number of the last price update. + function setLatestPriceSequenceNumber( + uint64 seqNr + ) external { + s_latestPriceSequenceNumber = seqNr; + } + + /// @notice Returns the sequence number of the last price update. + /// @return sequenceNumber The latest price update sequence number. + function getLatestPriceSequenceNumber() external view returns (uint64) { + return s_latestPriceSequenceNumber; + } + function emitCCIPMessageSent(uint64 destChainSelector, Internal.EVM2AnyRampMessage memory message) external { emit OnRamp.CCIPMessageSent(destChainSelector, message.header.sequenceNumber, message); } diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol index e760b79935d..68347d153fa 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol @@ -7,7 +7,7 @@ contract MultiOCR3Helper is MultiOCR3Base { event AfterConfigSet(uint8 ocrPluginType); /// @dev OCR plugin type used for transmit. - /// Defined in storage since it cannot be passed as calldata due to strict transmit checks + /// Defined in storage since it cannot be passed as calldata due to strict transmit checks uint8 internal s_transmitOcrPluginType; function setTransmitOcrPluginType( @@ -18,7 +18,7 @@ contract MultiOCR3Helper is MultiOCR3Base { /// @dev transmit function with signatures function transmitWithSignatures( - bytes32[3] calldata reportContext, + bytes32[2] calldata reportContext, bytes calldata report, bytes32[] calldata rs, bytes32[] calldata ss, @@ -28,7 +28,7 @@ contract MultiOCR3Helper is MultiOCR3Base { } /// @dev transmit function with no signatures - function transmitWithoutSignatures(bytes32[3] calldata reportContext, bytes calldata report) external { + function transmitWithoutSignatures(bytes32[2] calldata reportContext, bytes calldata report) external { bytes32[] memory emptySigs = new bytes32[](0); _transmit(s_transmitOcrPluginType, reportContext, report, emptySigs, emptySigs, bytes32("")); } diff --git a/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol b/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol index b323241a62d..c067b220fc0 100644 --- a/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol @@ -18,10 +18,6 @@ contract TokenPoolHelper is TokenPool { address router ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {} - function getRemotePoolHashes() external view returns (bytes32[] memory) { - return new bytes32[](0); // s_remotePoolHashes.values(); - } - function lockOrBurn( Pool.LockOrBurnInV1 calldata lockOrBurnIn ) external override returns (Pool.LockOrBurnOutV1 memory) { diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol index c6d948a70c2..2855b47eeea 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol @@ -47,7 +47,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { function test_TransmitSigners_gas_Success() public { vm.pauseGasMetering(); - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; // F = 2, need 2 signatures (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -65,7 +65,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { function test_TransmitWithoutSignatureVerification_gas_Success() public { vm.pauseGasMetering(); - bytes32[3] memory reportContext = [s_configDigest3, s_configDigest3, s_configDigest3]; + bytes32[2] memory reportContext = [s_configDigest3, s_configDigest3]; s_multiOCR3.setTransmitOcrPluginType(2); @@ -115,7 +115,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { // Randomise picked transmitter with random offset vm.startPrank(transmitters[randomAddressOffset % signersLength]); - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; // condition: matches signature expectation for transmit uint8 numSignatures = F + 1; @@ -138,7 +138,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { // Reverts function test_ForkedChain_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); @@ -155,7 +155,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_ZeroSignatures_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; s_multiOCR3.setTransmitOcrPluginType(0); @@ -165,7 +165,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_TooManySignatures_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; // 1 signature too many (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -179,7 +179,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_InsufficientSignatures_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; // Missing 1 signature for unique report (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -194,7 +194,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { function test_ConfigDigestMismatch_Revert() public { bytes32 configDigest; - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; + bytes32[2] memory reportContext = [configDigest, configDigest]; (,,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); @@ -205,7 +205,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_SignatureOutOfRegistration_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; bytes32[] memory rs = new bytes32[](2); bytes32[] memory ss = new bytes32[](1); @@ -218,7 +218,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_UnAuthorizedTransmitter_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; bytes32[] memory rs = new bytes32[](2); bytes32[] memory ss = new bytes32[](2); @@ -229,7 +229,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_NonUniqueSignature_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); @@ -247,7 +247,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_UnauthorizedSigner_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); @@ -264,7 +264,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { function test_UnconfiguredPlugin_Revert() public { bytes32 configDigest; - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; + bytes32[2] memory reportContext = [configDigest, configDigest]; s_multiOCR3.setTransmitOcrPluginType(42); @@ -273,7 +273,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_TransmitWithLessCalldataArgs_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; s_multiOCR3.setTransmitOcrPluginType(0); @@ -281,7 +281,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { vm.startPrank(s_validTransmitters[1]); // report length + function selector + report length + abiencoded location of report value + report context words - uint256 receivedLength = REPORT.length + 4 + 5 * 32; + uint256 receivedLength = REPORT.length + 4 + 4 * 32; vm.expectRevert( abi.encodeWithSelector( MultiOCR3Base.WrongMessageLength.selector, @@ -294,7 +294,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_TransmitWithExtraCalldataArgs_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; bytes32[] memory rs = new bytes32[](2); bytes32[] memory ss = new bytes32[](2); @@ -305,7 +305,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { // dynamic length + function selector + report length + abiencoded location of report value + report context words // rawVs value, lengths of rs, ss, and start locations of rs & ss -> 5 words - uint256 receivedLength = REPORT.length + 4 + (5 * 32) + (5 * 32) + (2 * 32) + (2 * 32); + uint256 receivedLength = REPORT.length + 4 + (4 * 32) + (5 * 32) + (2 * 32) + (2 * 32); vm.expectRevert( abi.encodeWithSelector( MultiOCR3Base.WrongMessageLength.selector, diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol index f949017d588..8418aa54cf1 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol @@ -95,7 +95,7 @@ contract MultiOCR3BaseSetup is BaseTest { function _getSignaturesForDigest( uint256[] memory signerPrivateKeys, bytes memory report, - bytes32[3] memory reportContext, + bytes32[2] memory reportContext, uint8 signatureCount ) internal pure returns (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) { rs = new bytes32[](signatureCount); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol index a942b98cc1e..7cfb9cd36b7 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol @@ -285,8 +285,7 @@ contract OffRamp_commit is OffRampSetup { function test_UnauthorizedTransmitter_Revert() public { OffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[3] memory reportContext = - [s_configDigestCommit, bytes32(uint256(s_latestSequenceNumber)), s_configDigestCommit]; + bytes32[2] memory reportContext = [s_configDigestCommit, bytes32(uint256(s_latestSequenceNumber))]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, F + 1); @@ -300,7 +299,7 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; + bytes32[2] memory reportContext = [bytes32(""), s_configDigestCommit]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, F + 1); @@ -325,7 +324,7 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; + bytes32[2] memory reportContext = [bytes32(""), s_configDigestCommit]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, F + 1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol index 9fd2499ef28..f12ca7b4609 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol @@ -198,7 +198,7 @@ contract OffRamp_execute is OffRampSetup { // Reverts function test_UnauthorizedTransmitter_Revert() public { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -216,7 +216,7 @@ contract OffRamp_execute is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; + bytes32[2] memory reportContext = [bytes32(""), s_configDigestExec]; vm.startPrank(s_validTransmitters[0]); vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); @@ -242,7 +242,7 @@ contract OffRamp_execute is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; + bytes32[2] memory reportContext = [bytes32(""), s_configDigestExec]; vm.startPrank(s_validTransmitters[0]); vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); @@ -277,7 +277,7 @@ contract OffRamp_execute is OffRampSetup { } function test_IncorrectArrayType_Revert() public { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; uint256[] memory wrongData = new uint256[](2); wrongData[0] = 1; @@ -288,7 +288,7 @@ contract OffRamp_execute is OffRampSetup { } function test_NonArray_Revert() public { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol index 45fa18930d9..727a7c63bb1 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol @@ -20,7 +20,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { vm.startPrank(address(s_offRamp)); } - function test_executeSingleMessage_NoTokens_Success() public { + function test_executeSingleMessage_NoTokens() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); @@ -44,7 +44,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_executeSingleMessage_WithTokens_Success() public { + function test_executeSingleMessage_WithTokens() public { Internal.Any2EVMRampMessage memory message = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)[0]; bytes[] memory offchainTokenData = new bytes[](message.tokenAmounts.length); @@ -69,7 +69,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, offchainTokenData, new uint32[](0)); } - function test_executeSingleMessage_WithVInterception_Success() public { + function test_executeSingleMessage_WithMessageInterceptor() public { vm.stopPrank(); vm.startPrank(OWNER); _enableInboundMessageInterceptor(); @@ -79,46 +79,47 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_NonContract_Success() public { + function test_executeSingleMessage_NonContract() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); message.receiver = STRANGER; s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_NonContractWithTokens_Success() public { + function test_executeSingleMessage_NonContractWithTokens() public { uint256[] memory amounts = new uint256[](2); amounts[0] = 1000; amounts[1] = 50; + + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + + message.receiver = STRANGER; + vm.expectEmit(); emit TokenPool.Released(address(s_offRamp), STRANGER, amounts[0]); vm.expectEmit(); emit TokenPool.Minted(address(s_offRamp), STRANGER, amounts[1]); - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); - message.receiver = STRANGER; + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } // Reverts - function test_TokenHandlingError_Revert() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; + function test_executeSingleMessage_RevertWhen_TokenHandlingError() public { + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithMaybeRevertingSingleToken(1, 50); + address destPool = s_destPoolByToken[message.tokenAmounts[0].destTokenAddress]; bytes memory errorMessage = "Random token pool issue"; - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); s_maybeRevertingPool.setShouldRevert(errorMessage); - vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, destPool, errorMessage)); s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_ZeroGasDONExecution_Revert() public { + function test_executeSingleMessage_RevertWhen_ZeroGasDONExecution() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); message.gasLimit = 0; @@ -128,7 +129,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_MessageSender_Revert() public { + function test_executeSingleMessage_RevertWhen_MessageSender() public { vm.stopPrank(); Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); @@ -136,7 +137,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_executeSingleMessage_WithFailingValidation_Revert() public { + function test_executeSingleMessage_RevertWhen_MessageValidationError() public { vm.stopPrank(); vm.startPrank(OWNER); _enableInboundMessageInterceptor(); @@ -153,7 +154,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() public { + function test_executeSingleMessage_RevertWhen_WithFailingValidationNoRouterCall() public { vm.stopPrank(); vm.startPrank(OWNER); _enableInboundMessageInterceptor(); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleReport.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleReport.t.sol index 4894cd2544c..7facff30cc4 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleReport.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleReport.t.sol @@ -425,7 +425,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_InvalidSourcePoolAddress_Success() public { + function test_InvalidSourcePoolAddress() public { address fakePoolAddress = address(0x0000000000333333); Internal.Any2EVMRampMessage[] memory messages = @@ -435,6 +435,8 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); + address destPool = s_destPoolByToken[messages[0].tokenAmounts[0].destTokenAddress]; + vm.recordLogs(); s_offRamp.executeSingleReport( @@ -448,6 +450,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( OffRamp.TokenHandlingError.selector, + destPool, abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, abi.encode(fakePoolAddress)) ) ); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol index 72999fad42f..f35db67abf6 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol @@ -78,13 +78,14 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); } - function test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() public { + function test_releaseOrMintToken_RevertWhen_TokenHandlingError_BalanceOf() public { uint256 amount = 123123; address token = s_sourceTokens[0]; + address destTokenAddress = s_destTokenBySourceToken[token]; Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: s_destTokenBySourceToken[token], + destTokenAddress: destTokenAddress, extraData: "", amount: amount, destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD @@ -93,11 +94,9 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { bytes memory revertData = "failed to balanceOf"; // Mock the call so returns 2 slots of data - vm.mockCallRevert( - s_destTokenBySourceToken[token], abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), revertData - ); + vm.mockCallRevert(destTokenAddress, abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), revertData); - vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, revertData)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, destTokenAddress, revertData)); s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); } @@ -198,13 +197,14 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); } - function test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() public { + function test_releaseOrMintSingleToken_RevertWhen_TokenHandlingError_transfer() public { address receiver = makeAddr("receiver"); uint256 amount = 123123; address token = s_sourceTokens[0]; address destToken = s_destTokenBySourceToken[token]; bytes memory originalSender = abi.encode(OWNER); bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); + address destPool = s_destPoolByToken[destToken]; Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), @@ -218,7 +218,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { vm.mockCallRevert(destToken, abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount), revertData); - vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, revertData)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, destPool, revertData)); s_offRamp.releaseOrMintSingleToken( tokenAmount, originalSender, receiver, SOURCE_CHAIN_SELECTOR_1, offchainTokenData ); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintTokens.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintTokens.t.sol index 74594f7031d..d2636ee08c8 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintTokens.t.sol @@ -18,7 +18,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { _setupMultipleOffRamps(); } - function test_releaseOrMintTokens_Success() public { + function test_releaseOrMintTokens() public { Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); IERC20 dstToken1 = IERC20(s_destFeeToken); uint256 startingBalance = dstToken1.balanceOf(OWNER); @@ -54,7 +54,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); } - function test_releaseOrMintTokens_WithGasOverride_Success() public { + function test_releaseOrMintTokens_WithGasOverride() public { Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); IERC20 dstToken1 = IERC20(s_destFeeToken); uint256 startingBalance = dstToken1.balanceOf(OWNER); @@ -94,7 +94,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); } - function test_releaseOrMintTokens_destDenominatedDecimals_Success() public { + function test_releaseOrMintTokens_destDenominatedDecimals() public { Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); uint256 amount = 100; uint256 destinationDenominationMultiplier = 1000; @@ -118,13 +118,15 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { // Revert - function test_TokenHandlingError_Reverts() public { + function test_releaseOrMintTokens_RevertWhen_TokenHandlingError() public { Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); bytes memory unknownError = bytes("unknown error"); s_maybeRevertingPool.setShouldRevert(unknownError); - vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, unknownError)); + vm.expectRevert( + abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, address(s_maybeRevertingPool), unknownError) + ); s_offRamp.releaseOrMintTokens( _getDefaultSourceTokenData(srcTokenAmounts), @@ -136,7 +138,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { ); } - function test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() public { + function test_releaseOrMintTokens_RevertWhenInvalidDataLengthReturnData() public { uint256 amount = 100; Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); srcTokenAmounts[0].amount = amount; @@ -170,7 +172,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { ); } - function test__releaseOrMintTokens_PoolIsNotAPool_Reverts() public { + function test_releaseOrMintTokens_RevertWhen_PoolIsNotAPool() public { // The offRamp is a contract, but not a pool address fakePoolAddress = address(s_offRamp); @@ -189,7 +191,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { ); } - function test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() public { + function test_releaseOrMintTokens_RevertWhenPoolDoesNotSupportDest() public { Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); uint256 amount1 = 100; srcTokenAmounts[0].amount = amount1; @@ -224,7 +226,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { /// forge-config: default.fuzz.runs = 32 /// forge-config: ccip.fuzz.runs = 1024 // Uint256 gives a good range of values to test, both inside and outside of the eth address space. - function testFuzz__releaseOrMintTokens_AnyRevertIsCaught_Success( + function testFuzz_releaseOrMintTokens_AnyRevertIsCaught( address destPool ) public { // Input 447301751254033913445893214690834296930546521452, which is 0x4E59B44847B379578588920CA78FBF26C0B4956C diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.trialExecute.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.trialExecute.t.sol index 8e944b91ab3..807cea5e268 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.trialExecute.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.trialExecute.t.sol @@ -14,18 +14,19 @@ contract OffRamp_trialExecute is OffRampSetup { _setupMultipleOffRamps(); } - function test_trialExecute_Success() public { + function test_trialExecute() public { uint256[] memory amounts = new uint256[](2); amounts[0] = 1000; amounts[1] = 50; - Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); IERC20 dstToken0 = IERC20(s_destTokens[0]); + uint256 startingBalance = dstToken0.balanceOf(message.receiver); (Internal.MessageExecutionState newState, bytes memory err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); assertEq("", err); @@ -33,48 +34,41 @@ contract OffRamp_trialExecute is OffRampSetup { assertEq(startingBalance + amounts[0], dstToken0.balanceOf(message.receiver)); } - function test_TokenHandlingErrorIsCaught_Success() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; + function test_trialExecute_TokenHandlingErrorIsCaught() public { + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithMaybeRevertingSingleToken(1, 10); + address destPool = s_destPoolByToken[message.tokenAmounts[0].destTokenAddress]; IERC20 dstToken0 = IERC20(s_destTokens[0]); uint256 startingBalance = dstToken0.balanceOf(OWNER); bytes memory errorMessage = "Random token pool issue"; - - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); s_maybeRevertingPool.setShouldRevert(errorMessage); (Internal.MessageExecutionState newState, bytes memory err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage), err); + assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, destPool, errorMessage), err); // Expect the balance to remain the same assertEq(startingBalance, dstToken0.balanceOf(OWNER)); } - function test_RateLimitError_Success() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; + function test_trialExecute_RateLimitError() public { + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithMaybeRevertingSingleToken(1, 10); + address destPool = s_destPoolByToken[message.tokenAmounts[0].destTokenAddress]; bytes memory errorMessage = abi.encodeWithSelector(RateLimiter.BucketOverfilled.selector); - - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); s_maybeRevertingPool.setShouldRevert(errorMessage); (Internal.MessageExecutionState newState, bytes memory err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage), err); + assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, destPool, errorMessage), err); } // TODO test actual pool exists but isn't compatible instead of just no pool - function test_TokenPoolIsNotAContract_Success() public { + function test_trialExecute_TokenPoolIsNotAContract() public { uint256[] memory amounts = new uint256[](2); amounts[0] = 10000; Internal.Any2EVMRampMessage memory message = diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol index 8e33f05c61d..858ee9e4a45 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol @@ -194,25 +194,36 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { return _generateAny2EVMMessage(sourceChainSelector, onRamp, sequenceNumber, tokenAmounts, false); } + function _generateAny2EVMMessageWithMaybeRevertingSingleToken( + uint64 sequenceNumber, + uint256 amount + ) internal view returns (Internal.Any2EVMRampMessage memory) { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0].token = s_sourceTokens[1]; + tokenAmounts[0].amount = amount; + + return _generateAny2EVMMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, sequenceNumber, tokenAmounts, false); + } + function _generateAny2EVMMessage( uint64 sourceChainSelector, bytes memory onRamp, uint64 sequenceNumber, - Client.EVMTokenAmount[] memory tokenAmounts, + Client.EVMTokenAmount[] memory sourceTokenAmounts, bool allowOutOfOrderExecution ) internal view returns (Internal.Any2EVMRampMessage memory) { bytes memory data = abi.encode(0); Internal.Any2EVMTokenTransfer[] memory any2EVMTokenTransfer = - new Internal.Any2EVMTokenTransfer[](tokenAmounts.length); + new Internal.Any2EVMTokenTransfer[](sourceTokenAmounts.length); // Correctly set the TokenDataPayload for each token. Tokens have to be set up in the TokenSetup. - for (uint256 i = 0; i < tokenAmounts.length; ++i) { + for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { any2EVMTokenTransfer[i] = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[tokenAmounts[i].token]), - destTokenAddress: s_destTokenBySourceToken[tokenAmounts[i].token], + sourcePoolAddress: abi.encode(s_sourcePoolByToken[sourceTokenAmounts[i].token]), + destTokenAddress: s_destTokenBySourceToken[sourceTokenAmounts[i].token], extraData: "", - amount: tokenAmounts[i].amount, + amount: sourceTokenAmounts[i].amount, destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); } @@ -360,7 +371,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { } function _commit(OffRamp.CommitReport memory commitReport, uint64 sequenceNumber) internal { - bytes32[3] memory reportContext = [s_configDigestCommit, bytes32(uint256(sequenceNumber)), s_configDigestCommit]; + bytes32[2] memory reportContext = [s_configDigestCommit, bytes32(uint256(sequenceNumber))]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, F + 1); @@ -372,7 +383,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { function _execute( Internal.ExecutionReport[] memory reports ) internal { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; vm.startPrank(s_validTransmitters[0]); s_offRamp.execute(reportContext, abi.encode(reports)); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol index dc1ef9d191c..287ee796f67 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {Router} from "../../../Router.sol"; import {Pool} from "../../../libraries/Pool.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; @@ -24,65 +25,93 @@ contract TokenPool_addRemotePool is TokenPoolSetup { assertEq(remotePools[1], remotePool); } - // function test_addRemotePool_MultipleActive() public { - // bytes[] memory remotePools = new bytes[](3); - // remotePools[0] = abi.encode(makeAddr("remotePool1")); - // remotePools[1] = abi.encode(makeAddr("remotePool2")); - // remotePools[2] = abi.encode(makeAddr("remotePool3")); - // - // address fakeOffRamp = makeAddr("fakeOffRamp"); - // - // vm.mockCall( - // address(s_sourceRouter), abi.encodeCall(Router.isOffRamp, (DEST_CHAIN_SELECTOR, fakeOffRamp)), abi.encode(true) - // ); - // - // vm.startPrank(fakeOffRamp); - // - // vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[0])); - // s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); - // - // // There's already one pool setup through the test setup - // assertEq(s_tokenPool.getRemotePoolHashes().length, 1); - // - // vm.startPrank(OWNER); - // s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePools[0]); - // - // vm.startPrank(fakeOffRamp); - // s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); - // - // // Adding an additional pool does not remove the previous one - // vm.startPrank(OWNER); - // s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePools[1]); - // - // // Both should now work - // assertEq(s_tokenPool.getRemotePoolHashes().length, 3); - // vm.startPrank(fakeOffRamp); - // s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); - // s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); - // - // // Adding a third pool, and removing the first one - // vm.startPrank(OWNER); - // s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePools[2]); - // assertEq(s_tokenPool.getRemotePoolHashes().length, 4); - // s_tokenPool.removeRemotePool(DEST_CHAIN_SELECTOR, remotePools[0]); - // assertEq(s_tokenPool.getRemotePoolHashes().length, 3); - // - // // Only the last two should work - // vm.startPrank(fakeOffRamp); - // vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[0])); - // s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); - // s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); - // s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[2])); - // - // // Removing the chain removes all associated pool hashes - // vm.startPrank(OWNER); - // - // uint64[] memory chainSelectorsToRemove = new uint64[](1); - // chainSelectorsToRemove[0] = DEST_CHAIN_SELECTOR; - // s_tokenPool.applyChainUpdates(chainSelectorsToRemove, new TokenPool.ChainUpdate[](0)); - // - // assertEq(s_tokenPool.getRemotePoolHashes().length, 0); - // } + function test_addRemotePool_MultipleActive() public { + bytes[] memory remotePools = new bytes[](3); + remotePools[0] = abi.encode(makeAddr("remotePool1")); + remotePools[1] = abi.encode(makeAddr("remotePool2")); + remotePools[2] = abi.encode(makeAddr("remotePool3")); + + address fakeOffRamp = makeAddr("fakeOffRamp"); + + vm.mockCall( + address(s_sourceRouter), abi.encodeCall(Router.isOffRamp, (DEST_CHAIN_SELECTOR, fakeOffRamp)), abi.encode(true) + ); + + vm.startPrank(fakeOffRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[0])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); + + // There's already one pool setup through the test setup + assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 1); + + vm.startPrank(OWNER); + s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePools[0]); + + vm.startPrank(fakeOffRamp); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); + + // Adding an additional pool does not remove the previous one + vm.startPrank(OWNER); + s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePools[1]); + + // Both should now work + assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 3); + vm.startPrank(fakeOffRamp); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); + + // Adding a third pool, and removing the first one + vm.startPrank(OWNER); + s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePools[2]); + assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 4); + s_tokenPool.removeRemotePool(DEST_CHAIN_SELECTOR, remotePools[0]); + assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 3); + + // Only the last two should work + vm.startPrank(fakeOffRamp); + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[0])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[2])); + + // Removing the chain removes all associated pool hashes + vm.startPrank(OWNER); + + uint64[] memory chainSelectorsToRemove = new uint64[](1); + chainSelectorsToRemove[0] = DEST_CHAIN_SELECTOR; + s_tokenPool.applyChainUpdates(chainSelectorsToRemove, new TokenPool.ChainUpdate[](0)); + + assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 0); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, DEST_CHAIN_SELECTOR)); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, DEST_CHAIN_SELECTOR)); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, DEST_CHAIN_SELECTOR)); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[2])); + + // Adding the chain back should NOT allow the previous pools to work again + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: abi.encode(s_initialRemoteToken), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + vm.startPrank(OWNER); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdate); + + vm.startPrank(fakeOffRamp); + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[0])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[1])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[2])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[2])); + } function _getReleaseOrMintInV1( bytes memory sourcePoolAddress diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol index 5594a36c31a..1ecfc83c5ce 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol @@ -136,74 +136,67 @@ contract TokenPool_applyChainUpdates is RouterSetup { s_tokenPool.applyChainUpdates(new uint64[](0), singleChainConfigured); } - // function test_applyChainUpdates_UpdatesRemotePoolHashes() public { - // assertEq(s_tokenPool.getRemotePoolHashes().length, 0); - // - // uint64 selector1 = 789; - // uint64 selector2 = 123; - // uint64 selector3 = 456; - // - // bytes memory pool1 = abi.encode(makeAddr("pool1")); - // bytes memory pool2 = abi.encode(makeAddr("pool2")); - // bytes memory pool3 = abi.encode(makeAddr("pool3")); - // - // TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](3); - // chainUpdates[0] = TokenPool.ChainUpdate({ - // remoteChainSelector: selector1, - // remotePoolAddress: pool1, - // remoteTokenAddress: pool1, - // outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - // inboundRateLimiterConfig: _getInboundRateLimiterConfig() - // }); - // chainUpdates[1] = TokenPool.ChainUpdate({ - // remoteChainSelector: selector2, - // remotePoolAddress: pool2, - // remoteTokenAddress: pool2, - // outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - // inboundRateLimiterConfig: _getInboundRateLimiterConfig() - // }); - // chainUpdates[2] = TokenPool.ChainUpdate({ - // remoteChainSelector: selector3, - // remotePoolAddress: pool3, - // remoteTokenAddress: pool3, - // outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - // inboundRateLimiterConfig: _getInboundRateLimiterConfig() - // }); - // - // s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); - // - // assertEq(s_tokenPool.getRemotePoolHashes().length, 3); - // - // // This adds 3 for the first chain, 2 for the second, and 1 for the third for a total of 6. - // // Since each chain already had one, the totals are 4 + 3 + 2 - // for (uint256 i = 0; i < chainUpdates.length; ++i) { - // for (uint256 j = i; j < chainUpdates.length; ++j) { - // s_tokenPool.addRemotePool(chainUpdates[i].remoteChainSelector, abi.encode(i, j)); - // } - // } - // - // assertEq(s_tokenPool.getRemotePoolHashes().length, 4 + 3 + 2); - // - // // Removing a chain should remove all associated pool hashes - // uint64[] memory chainRemoves = new uint64[](1); - // chainRemoves[0] = selector1; - // - // s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); - // - // assertEq(s_tokenPool.getRemotePoolHashes().length, 3 + 2); - // - // chainRemoves[0] = selector2; - // - // s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); - // - // assertEq(s_tokenPool.getRemotePoolHashes().length, 2); - // - // chainRemoves[0] = selector3; - // - // s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); - // - // assertEq(s_tokenPool.getRemotePoolHashes().length, 0); - // } + function test_applyChainUpdates_UpdatesRemotePoolHashes() public { + assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 0); + + uint64 selector1 = 789; + uint64 selector2 = 123; + uint64 selector3 = 456; + + bytes memory pool1 = abi.encode(makeAddr("pool1")); + bytes memory pool2 = abi.encode(makeAddr("pool2")); + bytes memory pool3 = abi.encode(makeAddr("pool3")); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](3); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: selector1, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: pool1, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: selector2, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: pool2, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[2] = TokenPool.ChainUpdate({ + remoteChainSelector: selector3, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: pool3, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + // This adds 3 for the first chain, 2 for the second, and 1 for the third for a total of 6. + for (uint256 i = 0; i < chainUpdates.length; ++i) { + for (uint256 j = i; j < chainUpdates.length; ++j) { + s_tokenPool.addRemotePool(chainUpdates[i].remoteChainSelector, abi.encode(i, j)); + } + assertEq(s_tokenPool.getRemotePools(chainUpdates[i].remoteChainSelector).length, 3 - i); + } + + // Removing a chain should remove all associated pool hashes + uint64[] memory chainRemoves = new uint64[](1); + chainRemoves[0] = selector1; + + s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); + + assertEq(s_tokenPool.getRemotePools(selector1).length, 0); + + chainRemoves[0] = selector2; + + s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); + + assertEq(s_tokenPool.getRemotePools(selector2).length, 0); + + // The above deletions should not have affected the third chain + assertEq(s_tokenPool.getRemotePools(selector3).length, 1); + } // Reverts diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol index 1b486fa3c8d..4262fac2218 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol @@ -1,8 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; +import {IERC20Metadata} from + "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + contract TokenPool_calculateLocalAmount is TokenPoolSetup { function test_calculateLocalAmount() public view { uint8 localDecimals = s_tokenPool.getTokenDecimals(); @@ -28,4 +33,69 @@ contract TokenPool_calculateLocalAmount is TokenPoolSetup { assertEq(s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals), expectedAmount); } } + + // Reverts + + function test_calculateLocalAmount_RevertWhen_LowRemoteDecimalsOverflows() public { + uint8 remoteDecimals = 0; + uint8 localDecimals = 78; + uint256 remoteAmount = 1; + + vm.mockCall(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(localDecimals)); + + s_tokenPool = + new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + + vm.expectRevert( + abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) + ); + + s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); + } + + function test_calculateLocalAmount_RevertWhen_HighLocalDecimalsOverflows() public { + uint8 remoteDecimals = 18; + uint8 localDecimals = 18 + 78; + uint256 remoteAmount = 1; + + vm.mockCall(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(localDecimals)); + + s_tokenPool = + new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + + vm.expectRevert( + abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) + ); + + s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); + } + + function test_calculateLocalAmount_RevertWhen_HighRemoteDecimalsOverflows() public { + uint8 remoteDecimals = 18 + 78; + uint8 localDecimals = 18; + uint256 remoteAmount = 1; + + vm.expectRevert( + abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) + ); + + s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); + } + + function test_calculateLocalAmount_RevertWhen_HighAmountOverflows() public { + uint8 remoteDecimals = 18; + uint8 localDecimals = 18 + 28; + uint256 remoteAmount = 1e50; + + vm.mockCall(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(localDecimals)); + + s_tokenPool = + new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + + vm.expectRevert( + abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) + ); + + s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); + } } diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol index 6d105ef54ae..4b643d66b9e 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol @@ -6,22 +6,46 @@ import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata} from + "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; contract TokenPool_constructor is TokenPoolSetup { - function test_immutableFields_Success() public view { + function test_constructor() public view { assertEq(address(s_token), address(s_tokenPool.getToken())); assertEq(address(s_mockRMN), s_tokenPool.getRmnProxy()); - assertEq(false, s_tokenPool.getAllowListEnabled()); + assertFalse(s_tokenPool.getAllowListEnabled()); assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); assertEq(DEFAULT_TOKEN_DECIMALS, s_tokenPool.getTokenDecimals()); } + function test_constructor_DecimalCallFails() public { + uint8 decimals = 255; + + vm.mockCallRevert(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), "decimals fails"); + + s_tokenPool = new TokenPoolHelper(s_token, decimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + + assertEq(s_tokenPool.getTokenDecimals(), decimals); + } + // Reverts - function test_ZeroAddressNotAllowed_Revert() public { + + function test_constructor_RevertWhen_ZeroAddressNotAllowed() public { vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); s_tokenPool = new TokenPoolHelper( IERC20(address(0)), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) ); } + + function test_constructor_RevertWhen_InvalidDecimalArgs() public { + uint8 invalidDecimals = DEFAULT_TOKEN_DECIMALS + 1; + + vm.expectRevert( + abi.encodeWithSelector(TokenPool.InvalidDecimalArgs.selector, invalidDecimals, DEFAULT_TOKEN_DECIMALS) + ); + + s_tokenPool = + new TokenPoolHelper(s_token, invalidDecimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + } } diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol index 004c71ccd02..9b318b782ce 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol @@ -1,61 +1,19 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; - import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../../../Router.sol"; -import {TokenPool} from "../../../../pools/TokenPool.sol"; + import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; -import {BaseTest} from "../../../BaseTest.t.sol"; -import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; -import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; - -contract HybridLockReleaseUSDCTokenPoolSetup is BaseTest { - IBurnMintERC20 internal s_token; - MockUSDCTokenMessenger internal s_mockUSDC; - MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; - uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; - - struct USDCMessage { - uint32 version; - uint32 sourceDomain; - uint32 destinationDomain; - uint64 nonce; - bytes32 sender; - bytes32 recipient; - bytes32 destinationCaller; - bytes messageBody; - } - - uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; - uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; - - bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); - address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); - address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); - address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); - - address internal s_routerAllowedOnRamp = address(3456); - address internal s_routerAllowedOffRamp = address(234); - Router internal s_router; +import {USDCSetup} from "../USDCSetup.t.sol"; +contract HybridLockReleaseUSDCTokenPoolSetup is USDCSetup { HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; address[] internal s_allowedList; function setUp() public virtual override { - BaseTest.setUp(); - BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); - s_token = usdcToken; - deal(address(s_token), OWNER, type(uint256).max); - _setUpRamps(); - - s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); - s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); - - usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + super.setUp(); s_usdcTokenPool = new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); @@ -63,32 +21,9 @@ contract HybridLockReleaseUSDCTokenPoolSetup is BaseTest { s_usdcTokenPoolTransferLiquidity = new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); - usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); - usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); - - bytes[] memory sourcePoolAddresses = new bytes[](1); - sourcePoolAddresses[0] = abi.encode(SOURCE_CHAIN_USDC_POOL); + BurnMintERC677(address(s_token)).grantMintAndBurnRoles(address(s_usdcTokenPool)); - bytes[] memory destPoolAddresses = new bytes[](1); - destPoolAddresses[0] = abi.encode(DEST_CHAIN_USDC_POOL); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddresses: sourcePoolAddresses, - remoteTokenAddress: abi.encode(address(s_token)), - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - chainUpdates[1] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddresses: destPoolAddresses, - remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_usdcTokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + _poolApplyChainUpdates(address(s_usdcTokenPool)); USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); domains[0] = USDCTokenPool.DomainUpdate({ @@ -100,38 +35,7 @@ contract HybridLockReleaseUSDCTokenPoolSetup is BaseTest { s_usdcTokenPool.setDomains(domains); - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); - s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); } - - function _setUpRamps() internal { - s_router = new Router(address(s_token), address(s_mockRMN)); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - address[] memory offRamps = new address[](1); - offRamps[0] = s_routerAllowedOffRamp; - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); - - s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } - - function _generateUSDCMessage( - USDCMessage memory usdcMessage - ) internal pure returns (bytes memory) { - return abi.encodePacked( - usdcMessage.version, - usdcMessage.sourceDomain, - usdcMessage.destinationDomain, - usdcMessage.nonce, - usdcMessage.sender, - usdcMessage.recipient, - usdcMessage.destinationCaller, - usdcMessage.messageBody - ); - } } diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol index 6ec63cc8e9e..f4f56cba3e6 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; -import {HybridLockReleaseUSDCTokenPoolSetup} from "../USDCTokenPoolSetup.t.sol"; +import {HybridLockReleaseUSDCTokenPoolSetup} from "./USDCBridgeMigratorSetup.t.sol"; contract USDCBridgeMigrator_cancelMigrationProposal is HybridLockReleaseUSDCTokenPoolSetup { function test_cancelExistingCCTPMigrationProposal_Success() public { diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol index 76e87f09852..855db7c5c64 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; -import {HybridLockReleaseUSDCTokenPoolSetup} from "../USDCTokenPoolSetup.t.sol"; +import {HybridLockReleaseUSDCTokenPoolSetup} from "./USDCBridgeMigratorSetup.t.sol"; contract USDCBridgeMigrator_excludeTokensFromBurn is HybridLockReleaseUSDCTokenPoolSetup { function test_excludeTokensWhenNoMigrationProposalPending_Revert() public { diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol index dd7ad2c2bf0..b2668bde801 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; -import {HybridLockReleaseUSDCTokenPoolSetup} from "../USDCTokenPoolSetup.t.sol"; +import {HybridLockReleaseUSDCTokenPoolSetup} from "./USDCBridgeMigratorSetup.t.sol"; contract USDCBridgeMigrator_proposeMigration is HybridLockReleaseUSDCTokenPoolSetup { function test_ChainNotUsingLockRelease_Revert() public { diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol new file mode 100644 index 00000000000..5a250fd16a8 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {USDCSetup} from "../USDCSetup.t.sol"; + +contract HybridLockReleaseUSDCTokenPoolSetup is USDCSetup { + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + + function setUp() public virtual override { + super.setUp(); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol similarity index 72% rename from contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPoolSetup.t.sol rename to contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol index 69712f7c68f..9ec89b52582 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPoolSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol @@ -6,18 +6,12 @@ import {IBurnMintERC20} from "../../../../shared/token/ERC20/IBurnMintERC20.sol" import {BurnMintERC677} from "../../../../shared/token/ERC677/BurnMintERC677.sol"; import {Router} from "../../../Router.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; -import {HybridLockReleaseUSDCTokenPool} from "../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; -import {USDCTokenPool} from "../../../pools/USDC/USDCTokenPool.sol"; + import {BaseTest} from "../../BaseTest.t.sol"; import {MockE2EUSDCTransmitter} from "../../mocks/MockE2EUSDCTransmitter.sol"; import {MockUSDCTokenMessenger} from "../../mocks/MockUSDCTokenMessenger.sol"; -contract HybridLockReleaseUSDCTokenPoolSetup is BaseTest { - IBurnMintERC20 internal s_token; - MockUSDCTokenMessenger internal s_mockUSDC; - MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; - uint32 internal constant USDC_DEST_TOKEN_GAS = 180_000; - +contract USDCSetup is BaseTest { struct USDCMessage { uint32 version; uint32 sourceDomain; @@ -29,6 +23,7 @@ contract HybridLockReleaseUSDCTokenPoolSetup is BaseTest { bytes messageBody; } + uint32 internal constant USDC_DEST_TOKEN_GAS = 180_000; uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; @@ -37,18 +32,20 @@ contract HybridLockReleaseUSDCTokenPoolSetup is BaseTest { address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + address internal s_routerAllowedOnRamp = address(3456); address internal s_routerAllowedOffRamp = address(234); Router internal s_router; - HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; - HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; - address[] internal s_allowedList; + IBurnMintERC20 internal s_token; function setUp() public virtual override { - BaseTest.setUp(); - BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + super.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("USD Coin", "USDC", 6, 0); s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); _setUpRamps(); @@ -56,16 +53,12 @@ contract HybridLockReleaseUSDCTokenPoolSetup is BaseTest { s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); - - s_usdcTokenPool = - new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); - - s_usdcTokenPoolTransferLiquidity = - new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); - usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); - usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + } + function _poolApplyChainUpdates( + address pool + ) internal { bytes[] memory sourcePoolAddresses = new bytes[](1); sourcePoolAddresses[0] = abi.encode(SOURCE_CHAIN_USDC_POOL); @@ -88,23 +81,7 @@ contract HybridLockReleaseUSDCTokenPoolSetup is BaseTest { inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - s_usdcTokenPool.applyChainUpdates(new uint64[](0), chainUpdates); - - USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); - domains[0] = USDCTokenPool.DomainUpdate({ - destChainSelector: DEST_CHAIN_SELECTOR, - domainIdentifier: 9999, - allowedCaller: keccak256("allowedCaller"), - enabled: true - }); - - s_usdcTokenPool.setDomains(domains); - - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); - - s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); - s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + TokenPool(pool).applyChainUpdates(new uint64[](0), chainUpdates); } function _setUpRamps() internal { diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol index 26dd4a0a71b..bc6108926b3 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol @@ -1,94 +1,27 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {BurnMintERC20} from "../../../../../shared/token/ERC20/BurnMintERC20.sol"; -import {Router} from "../../../../Router.sol"; -import {TokenPool} from "../../../../pools/TokenPool.sol"; import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; -import {BaseTest} from "../../../BaseTest.t.sol"; import {USDCTokenPoolHelper} from "../../../helpers/USDCTokenPoolHelper.sol"; -import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; -import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; - -contract USDCTokenPoolSetup is BaseTest { - IBurnMintERC20 internal s_token; - MockUSDCTokenMessenger internal s_mockUSDC; - MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; - uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; - - struct USDCMessage { - uint32 version; - uint32 sourceDomain; - uint32 destinationDomain; - uint64 nonce; - bytes32 sender; - bytes32 recipient; - bytes32 destinationCaller; - bytes messageBody; - } - - uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; - uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; - - bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); - address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); - address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); - address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); - - address internal s_routerAllowedOnRamp = address(3456); - address internal s_routerAllowedOffRamp = address(234); - Router internal s_router; +import {USDCSetup} from "../USDCSetup.t.sol"; +contract USDCTokenPoolSetup is USDCSetup { USDCTokenPoolHelper internal s_usdcTokenPool; USDCTokenPoolHelper internal s_usdcTokenPoolWithAllowList; address[] internal s_allowedList; function setUp() public virtual override { - BaseTest.setUp(); - BurnMintERC20 usdcToken = new BurnMintERC20("LINK", "LNK", 18, 0, 0); - s_token = usdcToken; - deal(address(s_token), OWNER, type(uint256).max); - _setUpRamps(); - - s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); - s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); - - usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + super.setUp(); s_usdcTokenPool = new USDCTokenPoolHelper(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); - usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); s_allowedList.push(USER_1); s_usdcTokenPoolWithAllowList = new USDCTokenPoolHelper(s_mockUSDC, s_token, s_allowedList, address(s_mockRMN), address(s_router)); - bytes[] memory sourcePoolAddresses = new bytes[](1); - sourcePoolAddresses[0] = abi.encode(SOURCE_CHAIN_USDC_POOL); - - bytes[] memory destPoolAddresses = new bytes[](1); - destPoolAddresses[0] = abi.encode(DEST_CHAIN_USDC_POOL); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddresses: sourcePoolAddresses, - remoteTokenAddress: abi.encode(address(s_token)), - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - chainUpdates[1] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddresses: destPoolAddresses, - remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_usdcTokenPool.applyChainUpdates(new uint64[](0), chainUpdates); - s_usdcTokenPoolWithAllowList.applyChainUpdates(new uint64[](0), chainUpdates); + _poolApplyChainUpdates(address(s_usdcTokenPool)); + _poolApplyChainUpdates(address(s_usdcTokenPoolWithAllowList)); USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); domains[0] = USDCTokenPool.DomainUpdate({ @@ -101,32 +34,4 @@ contract USDCTokenPoolSetup is BaseTest { s_usdcTokenPool.setDomains(domains); s_usdcTokenPoolWithAllowList.setDomains(domains); } - - function _setUpRamps() internal { - s_router = new Router(address(s_token), address(s_mockRMN)); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - address[] memory offRamps = new address[](1); - offRamps[0] = s_routerAllowedOffRamp; - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); - - s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } - - function _generateUSDCMessage( - USDCMessage memory usdcMessage - ) internal pure returns (bytes memory) { - return abi.encodePacked( - usdcMessage.version, - usdcMessage.sourceDomain, - usdcMessage.destinationDomain, - usdcMessage.nonce, - usdcMessage.sender, - usdcMessage.recipient, - usdcMessage.destinationCaller, - usdcMessage.messageBody - ); - } } diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.constructor.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.constructor.t.sol index 1cc9d9addb7..413ef4a6797 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.constructor.t.sol @@ -1,16 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {RMNRemote} from "../../../rmn/RMNRemote.sol"; import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; contract RMNRemote_constructor is RMNRemoteSetup { - function test_constructor_success() public view { + function test_constructor() public view { assertEq(s_rmnRemote.getLocalChainSelector(), 1); } - - function test_constructor_zeroChainSelector_reverts() public { - vm.expectRevert(RMNRemote.ZeroValueNotAllowed.selector); - new RMNRemote(0); - } } diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.isBlessed.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.isBlessed.t.sol new file mode 100644 index 00000000000..aabfe74bf4d --- /dev/null +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.isBlessed.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRMN} from "../../../interfaces/IRMN.sol"; + +import {RMNRemote} from "../../../rmn/RMNRemote.sol"; +import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; + +contract RMNRemote_isBlessed is RMNRemoteSetup { + function test_isBlessed() public { + IRMN.TaggedRoot memory taggedRoot = IRMN.TaggedRoot({root: keccak256("root"), commitStore: makeAddr("commitStore")}); + + vm.mockCall( + address(s_legacyRMN), abi.encodeWithSelector(s_legacyRMN.isBlessed.selector, taggedRoot), abi.encode(true) + ); + + assertTrue(s_rmnRemote.isBlessed(taggedRoot)); + + vm.mockCall( + address(s_legacyRMN), abi.encodeWithSelector(s_legacyRMN.isBlessed.selector, taggedRoot), abi.encode(false) + ); + + assertFalse(s_rmnRemote.isBlessed(taggedRoot)); + } + + function test_isBlessed_RevertWhen_IsBlessedNotAvailable() public { + IRMN.TaggedRoot memory taggedRoot = IRMN.TaggedRoot({root: keccak256("root"), commitStore: makeAddr("commitStore")}); + + s_rmnRemote = new RMNRemote(100, IRMN(address(0))); + + vm.expectRevert(RMNRemote.IsBlessedNotAvailable.selector); + s_rmnRemote.isBlessed(taggedRoot); + } +} diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemoteSetup.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemoteSetup.t.sol index b32dcd98a1a..afb65eeab11 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemoteSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemoteSetup.t.sol @@ -1,7 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {IRMN} from "../../../interfaces/IRMN.sol"; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; + import {Internal} from "../../../libraries/Internal.sol"; import {RMNRemote} from "../../../rmn/RMNRemote.sol"; import {BaseTest} from "../../BaseTest.t.sol"; @@ -21,9 +23,11 @@ contract RMNRemoteSetup is BaseTest { bytes16 internal constant CURSE_SUBJ_2 = bytes16(keccak256("subject 2")); bytes16[] internal s_curseSubjects; + IRMN internal s_legacyRMN = IRMN(makeAddr("legacyRMN")); + function setUp() public virtual override { super.setUp(); - s_rmnRemote = new RMNRemote(1); + s_rmnRemote = new RMNRemote(1, s_legacyRMN); OFF_RAMP_ADDRESS = makeAddr("OFF RAMP"); s_curseSubjects = [CURSE_SUBJ_1, CURSE_SUBJ_2]; diff --git a/contracts/src/v0.8/keystone/BalanceReader.sol b/contracts/src/v0.8/keystone/BalanceReader.sol new file mode 100644 index 00000000000..2efd6a84605 --- /dev/null +++ b/contracts/src/v0.8/keystone/BalanceReader.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +/// @notice BalanceReader is used to read native currency balances from one or more accounts +/// using a contract method instead of an RPC "eth_getBalance" call. +contract BalanceReader { + function getNativeBalances(address[] memory addresses) public view returns (uint256[] memory) { + uint256[] memory balances = new uint256[](addresses.length); + for (uint256 i = 0; i < addresses.length; ++i) { + balances[i] = addresses[i].balance; + } + return balances; + } +} diff --git a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol index 447c979d405..2f57a00bf04 100644 --- a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol +++ b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol @@ -7,7 +7,7 @@ import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator, IERC165 { +contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator { event FeedReceived(bytes32 indexed feedId, uint224 price, uint32 timestamp); error UnauthorizedSender(address sender); @@ -101,7 +101,7 @@ contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator, IERC165 { return (report.Price, report.Timestamp); } - function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } } diff --git a/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol b/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol index 708fdc8e692..809081b92e0 100644 --- a/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol +++ b/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol @@ -10,11 +10,11 @@ abstract contract KeystoneFeedsPermissionHandler is Ownable2StepMsgSender { /// @notice Holds the details for permissions of a report /// @dev Workflow names and report names are stored as bytes to optimize for gas efficiency. struct Permission { - address forwarder; // ──────╮ The address of the forwarder (20 bytes) - bytes10 workflowName; // │ The name of the workflow in bytes10 - bytes2 reportName; // ──────╯ The name of the report in bytes2 - address workflowOwner; // ──╮ The address of the workflow owner (20 bytes) - bool isAllowed; // ─────────╯ Whether the report is allowed or not (1 byte) + address forwarder; // ─────╮ The address of the forwarder (20 bytes) + bytes10 workflowName; // │ The name of the workflow in bytes10 + bytes2 reportName; // ─────╯ The name of the report in bytes2 + address workflowOwner; // ─╮ The address of the workflow owner (20 bytes) + bool isAllowed; // ────────╯ Whether the report is allowed or not (1 byte) } /// @notice Event emitted when report permissions are set diff --git a/contracts/src/v0.8/keystone/interfaces/IReceiver.sol b/contracts/src/v0.8/keystone/interfaces/IReceiver.sol index 9afa1d340a3..b18e35d6b5f 100644 --- a/contracts/src/v0.8/keystone/interfaces/IReceiver.sol +++ b/contracts/src/v0.8/keystone/interfaces/IReceiver.sol @@ -1,8 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; + /// @title IReceiver - receives keystone reports -interface IReceiver { +/// @notice Implementations must support the IReceiver interface through ERC165. +interface IReceiver is IERC165 { /// @notice Handles incoming keystone reports. /// @dev If this function call reverts, it can be retried with a higher gas /// limit. The receiver is responsible for discarding stale reports. diff --git a/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol b/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol index 8f039b5f0ce..71fb731d0ad 100644 --- a/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol +++ b/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {IReceiver} from "../../interfaces/IReceiver.sol"; -contract MaliciousReportReceiver is IReceiver, IERC165 { +contract MaliciousReportReceiver is IReceiver { event MessageReceived(bytes metadata, bytes[] mercuryReports); bytes public latestReport; diff --git a/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol b/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol index f45e95afb2c..c749b50dafe 100644 --- a/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol +++ b/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol @@ -6,7 +6,7 @@ import {IReceiver} from "../../interfaces/IReceiver.sol"; /// A malicious receiver that uses max allowed for ERC165 checks and consumes all gas in `onReport()` /// Causes parent Forwarder contract to revert if it doesn't handle gas tracking accurately -contract MaliciousRevertingReceiver is IReceiver, IERC165 { +contract MaliciousRevertingReceiver is IReceiver { function onReport(bytes calldata, bytes calldata) external view override { // consumes about 63/64 of all gas available uint256 targetGasRemaining = 200; diff --git a/contracts/src/v0.8/keystone/test/mocks/Receiver.sol b/contracts/src/v0.8/keystone/test/mocks/Receiver.sol index d4005950ade..0604a145c6b 100644 --- a/contracts/src/v0.8/keystone/test/mocks/Receiver.sol +++ b/contracts/src/v0.8/keystone/test/mocks/Receiver.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {IReceiver} from "../../interfaces/IReceiver.sol"; -contract Receiver is IReceiver, IERC165 { +contract Receiver is IReceiver { event MessageReceived(bytes metadata, bytes[] mercuryReports); bytes public latestReport; @@ -18,7 +18,7 @@ contract Receiver is IReceiver, IERC165 { emit MessageReceived(metadata, mercuryReports); } - function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } } diff --git a/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol b/contracts/src/v0.8/l2ep/CrossDomainDelegateForwarder.sol similarity index 100% rename from contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol rename to contracts/src/v0.8/l2ep/CrossDomainDelegateForwarder.sol diff --git a/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/CrossDomainForwarder.sol similarity index 100% rename from contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol rename to contracts/src/v0.8/l2ep/CrossDomainForwarder.sol diff --git a/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol b/contracts/src/v0.8/l2ep/CrossDomainOwnable.sol similarity index 96% rename from contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol rename to contracts/src/v0.8/l2ep/CrossDomainOwnable.sol index c85762b6fca..7e1c0d1adb9 100644 --- a/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol +++ b/contracts/src/v0.8/l2ep/CrossDomainOwnable.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; import {ICrossDomainOwnable} from "./interfaces/ICrossDomainOwnable.sol"; /** diff --git a/contracts/src/v0.8/l2ep/dev/Flags.sol b/contracts/src/v0.8/l2ep/Flags.sol similarity index 95% rename from contracts/src/v0.8/l2ep/dev/Flags.sol rename to contracts/src/v0.8/l2ep/Flags.sol index 2dc030d7d59..2ac35be4ce7 100644 --- a/contracts/src/v0.8/l2ep/dev/Flags.sol +++ b/contracts/src/v0.8/l2ep/Flags.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import {SimpleReadAccessController} from "../../shared/access/SimpleReadAccessController.sol"; -import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {SimpleReadAccessController} from "../shared/access/SimpleReadAccessController.sol"; +import {AccessControllerInterface} from "../shared/interfaces/AccessControllerInterface.sol"; +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; /* dev dependencies - to be re/moved after audit */ import {IFlags} from "./interfaces/IFlags.sol"; diff --git a/contracts/src/v0.8/l2ep/README.md b/contracts/src/v0.8/l2ep/README.md index 21a537c4fe7..83eb6fe9372 100644 --- a/contracts/src/v0.8/l2ep/README.md +++ b/contracts/src/v0.8/l2ep/README.md @@ -11,7 +11,8 @@ Emergency Protocol (L2EP) contracts. It is organized as follows: ## The `/dev` Folder -The `/dev` folder contains subfolders for each chain that +The `/dev` folder contains contracts that has not yet been audited. +The root folder contains subfolders for each chain that has an L2EP solution implemented for it (e.g. `/scroll`, `/arbitrum`, `/optimism`). It also contains a subfolder named `/interfaces`, which stores shared interface types between all the supported diff --git a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/arbitrum/ArbitrumCrossDomainForwarder.sol similarity index 89% rename from contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol rename to contracts/src/v0.8/l2ep/arbitrum/ArbitrumCrossDomainForwarder.sol index 0db657ee71c..e3ef117d23e 100644 --- a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol +++ b/contracts/src/v0.8/l2ep/arbitrum/ArbitrumCrossDomainForwarder.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; // solhint-disable-next-line no-unused-import import {IForwarder} from "../interfaces/IForwarder.sol"; import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; -import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {AddressAliasHelper} from "../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /** * @title ArbitrumCrossDomainForwarder - L1 xDomain account representation diff --git a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol b/contracts/src/v0.8/l2ep/arbitrum/ArbitrumCrossDomainGovernor.sol similarity index 93% rename from contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol rename to contracts/src/v0.8/l2ep/arbitrum/ArbitrumCrossDomainGovernor.sol index 60d9cc52666..f5ed8d7a9d2 100644 --- a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol +++ b/contracts/src/v0.8/l2ep/arbitrum/ArbitrumCrossDomainGovernor.sol @@ -2,14 +2,14 @@ pragma solidity ^0.8.0; // solhint-disable-next-line no-unused-import -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; // solhint-disable-next-line no-unused-import import {IForwarder} from "../interfaces/IForwarder.sol"; import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; import {ArbitrumCrossDomainForwarder} from "./ArbitrumCrossDomainForwarder.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /** * @title ArbitrumCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Arbitrum diff --git a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/arbitrum/ArbitrumSequencerUptimeFeed.sol similarity index 94% rename from contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/arbitrum/ArbitrumSequencerUptimeFeed.sol index 678bef3a853..1ba6b9b54b3 100644 --- a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/arbitrum/ArbitrumSequencerUptimeFeed.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; -import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; -import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {AddressAliasHelper} from "../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {AggregatorInterface} from "../../shared/interfaces/AggregatorInterface.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {AggregatorV2V3Interface} from "../../shared/interfaces/AggregatorV2V3Interface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IFlags} from "../interfaces/IFlags.sol"; import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; -import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; +import {SimpleReadAccessController} from "../../shared/access/SimpleReadAccessController.sol"; /** * @title ArbitrumSequencerUptimeFeed - L2 sequencer uptime status aggregator diff --git a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol b/contracts/src/v0.8/l2ep/arbitrum/ArbitrumValidator.sol similarity index 95% rename from contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol rename to contracts/src/v0.8/l2ep/arbitrum/ArbitrumValidator.sol index 05f9349eb62..3d30f38981c 100644 --- a/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol +++ b/contracts/src/v0.8/l2ep/arbitrum/ArbitrumValidator.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol"; -import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; +import {AggregatorValidatorInterface} from "../../shared/interfaces/AggregatorValidatorInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol"; +import {SimpleWriteAccessController} from "../../shared/access/SimpleWriteAccessController.sol"; /* ./dev dependencies - to be moved from ./dev after audit */ import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; import {IArbitrumDelayedInbox} from "../interfaces/IArbitrumDelayedInbox.sol"; -import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {ArbSys} from "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {AddressAliasHelper} from "../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /** * @title ArbitrumValidator - makes xDomain L2 Flags contract call (using L2 xDomain Forwarder contract) diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol b/contracts/src/v0.8/l2ep/interfaces/IArbitrumDelayedInbox.sol similarity index 84% rename from contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol rename to contracts/src/v0.8/l2ep/interfaces/IArbitrumDelayedInbox.sol index e18efd65ad2..802ec06b168 100644 --- a/contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol +++ b/contracts/src/v0.8/l2ep/interfaces/IArbitrumDelayedInbox.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {IInbox} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol"; +import {IInbox} from "../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol"; /** * @notice This interface extends Arbitrum's IInbox interface to include diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol b/contracts/src/v0.8/l2ep/interfaces/ICrossDomainOwnable.sol similarity index 100% rename from contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol rename to contracts/src/v0.8/l2ep/interfaces/ICrossDomainOwnable.sol diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol b/contracts/src/v0.8/l2ep/interfaces/IDelegateForwarder.sol similarity index 100% rename from contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol rename to contracts/src/v0.8/l2ep/interfaces/IDelegateForwarder.sol diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol b/contracts/src/v0.8/l2ep/interfaces/IFlags.sol similarity index 100% rename from contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol rename to contracts/src/v0.8/l2ep/interfaces/IFlags.sol diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol b/contracts/src/v0.8/l2ep/interfaces/IForwarder.sol similarity index 100% rename from contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol rename to contracts/src/v0.8/l2ep/interfaces/IForwarder.sol diff --git a/contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/interfaces/ISequencerUptimeFeed.sol similarity index 100% rename from contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/interfaces/ISequencerUptimeFeed.sol diff --git a/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/optimism/OptimismCrossDomainForwarder.sol similarity index 91% rename from contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol rename to contracts/src/v0.8/l2ep/optimism/OptimismCrossDomainForwarder.sol index 1d037886960..f2b4fafc32d 100644 --- a/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol +++ b/contracts/src/v0.8/l2ep/optimism/OptimismCrossDomainForwarder.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; // solhint-disable-next-line no-unused-import import {IForwarder} from "../interfaces/IForwarder.sol"; @@ -9,8 +9,8 @@ import {IForwarder} from "../interfaces/IForwarder.sol"; import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; -import {iOVM_CrossDomainMessenger} from "../../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {iOVM_CrossDomainMessenger} from "../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /** * @title OptimismCrossDomainForwarder - L1 xDomain account representation diff --git a/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol b/contracts/src/v0.8/l2ep/optimism/OptimismCrossDomainGovernor.sol similarity index 91% rename from contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol rename to contracts/src/v0.8/l2ep/optimism/OptimismCrossDomainGovernor.sol index 6a41bd98f03..61bed5a6903 100644 --- a/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol +++ b/contracts/src/v0.8/l2ep/optimism/OptimismCrossDomainGovernor.sol @@ -7,8 +7,8 @@ import {IForwarder} from "../interfaces/IForwarder.sol"; import {OptimismCrossDomainForwarder} from "./OptimismCrossDomainForwarder.sol"; -import {iOVM_CrossDomainMessenger} from "../../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {iOVM_CrossDomainMessenger} from "../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /** * @title OptimismCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Optimism diff --git a/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/optimism/OptimismSequencerUptimeFeed.sol similarity index 100% rename from contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/optimism/OptimismSequencerUptimeFeed.sol diff --git a/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol b/contracts/src/v0.8/l2ep/optimism/OptimismValidator.sol similarity index 100% rename from contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol rename to contracts/src/v0.8/l2ep/optimism/OptimismValidator.sol diff --git a/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/scroll/ScrollCrossDomainForwarder.sol similarity index 94% rename from contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol rename to contracts/src/v0.8/l2ep/scroll/ScrollCrossDomainForwarder.sol index c70bc794afb..35e8b4827d3 100644 --- a/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol +++ b/contracts/src/v0.8/l2ep/scroll/ScrollCrossDomainForwarder.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IForwarder} from "../interfaces/IForwarder.sol"; import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; import {IScrollMessenger} from "@scroll-tech/contracts/libraries/IScrollMessenger.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /// @title ScrollCrossDomainForwarder - L1 xDomain account representation /// @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. diff --git a/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol b/contracts/src/v0.8/l2ep/scroll/ScrollCrossDomainGovernor.sol similarity index 96% rename from contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol rename to contracts/src/v0.8/l2ep/scroll/ScrollCrossDomainGovernor.sol index dae621e9b08..7170cc2e491 100644 --- a/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol +++ b/contracts/src/v0.8/l2ep/scroll/ScrollCrossDomainGovernor.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; // solhint-disable-next-line no-unused-import import {IForwarder} from "../interfaces/IForwarder.sol"; @@ -10,7 +10,7 @@ import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; import {IScrollMessenger} from "@scroll-tech/contracts/libraries/IScrollMessenger.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /// @title ScrollCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Scroll /// @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. diff --git a/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/scroll/ScrollSequencerUptimeFeed.sol similarity index 100% rename from contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/scroll/ScrollSequencerUptimeFeed.sol diff --git a/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol b/contracts/src/v0.8/l2ep/scroll/ScrollValidator.sol similarity index 100% rename from contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol rename to contracts/src/v0.8/l2ep/scroll/ScrollValidator.sol diff --git a/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/shared/BaseSequencerUptimeFeed.sol similarity index 94% rename from contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/shared/BaseSequencerUptimeFeed.sol index 15c20504569..344270fcff8 100644 --- a/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/shared/BaseSequencerUptimeFeed.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; -import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; -import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {AggregatorInterface} from "../../shared/interfaces/AggregatorInterface.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {AggregatorV2V3Interface} from "../../shared/interfaces/AggregatorV2V3Interface.sol"; import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; -import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; +import {SimpleReadAccessController} from "../../shared/access/SimpleReadAccessController.sol"; /// @title L2 sequencer uptime status aggregator /// @notice L2 contract that receives status updates from a specific L1 address, diff --git a/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol b/contracts/src/v0.8/l2ep/shared/BaseValidator.sol similarity index 88% rename from contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol rename to contracts/src/v0.8/l2ep/shared/BaseValidator.sol index 33df388972f..8b38da391ec 100644 --- a/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol +++ b/contracts/src/v0.8/l2ep/shared/BaseValidator.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {AggregatorValidatorInterface} from "../../shared/interfaces/AggregatorValidatorInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; +import {SimpleWriteAccessController} from "../../shared/access/SimpleWriteAccessController.sol"; abstract contract BaseValidator is SimpleWriteAccessController, AggregatorValidatorInterface, ITypeAndVersion { /// @notice emitted when gas cost to spend on L2 is updated diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol index cff9b953e2e..e0a76a2b37a 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {ArbitrumCrossDomainForwarder} from "../../../dev/arbitrum/ArbitrumCrossDomainForwarder.sol"; +import {ArbitrumCrossDomainForwarder} from "../../../arbitrum/ArbitrumCrossDomainForwarder.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol index 610f49f16c4..746da3d1cef 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {ArbitrumCrossDomainGovernor} from "../../../dev/arbitrum/ArbitrumCrossDomainGovernor.sol"; +import {ArbitrumCrossDomainGovernor} from "../../../arbitrum/ArbitrumCrossDomainGovernor.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol index e308ead3432..deaa81977b7 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol @@ -2,10 +2,10 @@ pragma solidity 0.8.24; import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; -import {ArbitrumSequencerUptimeFeed} from "../../../dev/arbitrum/ArbitrumSequencerUptimeFeed.sol"; +import {ArbitrumSequencerUptimeFeed} from "../../../arbitrum/ArbitrumSequencerUptimeFeed.sol"; import {MockAggregatorV2V3} from "../../mocks/MockAggregatorV2V3.sol"; import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; -import {Flags} from "../../../dev/Flags.sol"; +import {Flags} from "../../../Flags.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; contract ArbitrumSequencerUptimeFeedTest is L2EPTest { diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol index ab872991749..95278e644b1 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol @@ -4,8 +4,8 @@ pragma solidity 0.8.24; import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; -import {ArbitrumSequencerUptimeFeed} from "../../../dev/arbitrum/ArbitrumSequencerUptimeFeed.sol"; -import {ArbitrumValidator} from "../../../dev/arbitrum/ArbitrumValidator.sol"; +import {ArbitrumSequencerUptimeFeed} from "../../../arbitrum/ArbitrumSequencerUptimeFeed.sol"; +import {ArbitrumValidator} from "../../../arbitrum/ArbitrumValidator.sol"; import {MockArbitrumInbox} from "../../../../tests/MockArbitrumInbox.sol"; import {MockAggregatorV2V3} from "../../mocks/MockAggregatorV2V3.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol index c0e82ab8d5e..28d70fa35a5 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {OptimismCrossDomainForwarder} from "../../../dev/optimism/OptimismCrossDomainForwarder.sol"; +import {OptimismCrossDomainForwarder} from "../../../optimism/OptimismCrossDomainForwarder.sol"; import {MockOVMCrossDomainMessenger} from "../../mocks/optimism/MockOVMCrossDomainMessenger.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol index 8f8fb9d7e7c..57f79124512 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {OptimismCrossDomainGovernor} from "../../../dev/optimism/OptimismCrossDomainGovernor.sol"; +import {OptimismCrossDomainGovernor} from "../../../optimism/OptimismCrossDomainGovernor.sol"; import {MockOVMCrossDomainMessenger} from "../../mocks/optimism/MockOVMCrossDomainMessenger.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol index eec9657ac14..daf50962a1e 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol @@ -3,8 +3,8 @@ pragma solidity 0.8.24; import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; -import {OptimismSequencerUptimeFeed} from "../../../dev/optimism/OptimismSequencerUptimeFeed.sol"; -import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; +import {OptimismSequencerUptimeFeed} from "../../../optimism/OptimismSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../../../shared/BaseSequencerUptimeFeed.sol"; import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol index 59395bf5d8b..ba9e3f872f1 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; +import {ISequencerUptimeFeed} from "../../../interfaces/ISequencerUptimeFeed.sol"; import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; -import {OptimismSequencerUptimeFeed} from "../../../dev/optimism/OptimismSequencerUptimeFeed.sol"; -import {OptimismValidator} from "../../../dev/optimism/OptimismValidator.sol"; +import {OptimismSequencerUptimeFeed} from "../../../optimism/OptimismSequencerUptimeFeed.sol"; +import {OptimismValidator} from "../../../optimism/OptimismValidator.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; contract OptimismValidatorTest is L2EPTest { diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol index e34e84f4006..b0ef7df22c1 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; import {MockScrollCrossDomainMessenger} from "../../mocks/scroll/MockScrollCrossDomainMessenger.sol"; -import {ScrollCrossDomainForwarder} from "../../../dev/scroll/ScrollCrossDomainForwarder.sol"; +import {ScrollCrossDomainForwarder} from "../../../scroll/ScrollCrossDomainForwarder.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol index 8c3d56d1560..5eefaddab70 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; import {MockScrollCrossDomainMessenger} from "../../mocks/scroll/MockScrollCrossDomainMessenger.sol"; -import {ScrollCrossDomainGovernor} from "../../../dev/scroll/ScrollCrossDomainGovernor.sol"; +import {ScrollCrossDomainGovernor} from "../../../scroll/ScrollCrossDomainGovernor.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol index 0968c69415f..5e4d8a7a20f 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol @@ -3,8 +3,8 @@ pragma solidity 0.8.24; import {MockScrollL1CrossDomainMessenger} from "../../mocks/scroll/MockScrollL1CrossDomainMessenger.sol"; import {MockScrollL2CrossDomainMessenger} from "../../mocks/scroll/MockScrollL2CrossDomainMessenger.sol"; -import {ScrollSequencerUptimeFeed} from "../../../dev/scroll/ScrollSequencerUptimeFeed.sol"; -import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; +import {ScrollSequencerUptimeFeed} from "../../../scroll/ScrollSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../../../shared/BaseSequencerUptimeFeed.sol"; import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol index 3d5298d5184..1a0bcc856f2 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; +import {ISequencerUptimeFeed} from "../../../interfaces/ISequencerUptimeFeed.sol"; import {MockScrollL1CrossDomainMessenger} from "../../mocks/scroll/MockScrollL1CrossDomainMessenger.sol"; import {MockScrollL2CrossDomainMessenger} from "../../mocks/scroll/MockScrollL2CrossDomainMessenger.sol"; import {MockScrollL1MessageQueue} from "../../mocks/scroll/MockScrollL1MessageQueue.sol"; -import {ScrollSequencerUptimeFeed} from "../../../dev/scroll/ScrollSequencerUptimeFeed.sol"; -import {ScrollValidator} from "../../../dev/scroll/ScrollValidator.sol"; +import {ScrollSequencerUptimeFeed} from "../../../scroll/ScrollSequencerUptimeFeed.sol"; +import {ScrollValidator} from "../../../scroll/ScrollValidator.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; contract ScrollValidatorTest is L2EPTest { diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol index 6d90b3973e9..5b319d32407 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.24; import {AddressAliasHelper} from "../../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {ZKSyncSequencerUptimeFeed} from "../../../dev/zksync/ZKSyncSequencerUptimeFeed.sol"; -import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; +import {ZKSyncSequencerUptimeFeed} from "../../../zksync/ZKSyncSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../../../shared/BaseSequencerUptimeFeed.sol"; import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol index 0bea147c8cd..1a0f16d6ae0 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.24; import {MockBridgehub} from "../../mocks/zksync/MockZKSyncL1Bridge.sol"; -import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; -import {ZKSyncValidator} from "../../../dev/zksync/ZKSyncValidator.sol"; -import {BaseValidator} from "../../../dev/shared/BaseValidator.sol"; +import {ISequencerUptimeFeed} from "../../../interfaces/ISequencerUptimeFeed.sol"; +import {ZKSyncValidator} from "../../../zksync/ZKSyncValidator.sol"; +import {BaseValidator} from "../../../shared/BaseValidator.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; contract ZKSyncValidatorTest is L2EPTest { diff --git a/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/zksync/ZKSyncSequencerUptimeFeed.sol similarity index 89% rename from contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/zksync/ZKSyncSequencerUptimeFeed.sol index 0074a0277d1..cb520d2d0ac 100644 --- a/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/zksync/ZKSyncSequencerUptimeFeed.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.19; import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; -import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {AddressAliasHelper} from "../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; /// @title ZKSyncSequencerUptimeFeed - L2 sequencer uptime status aggregator /// @notice L2 contract that receives status updates from a specific L1 address, diff --git a/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol b/contracts/src/v0.8/l2ep/zksync/ZKSyncValidator.sol similarity index 100% rename from contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol rename to contracts/src/v0.8/l2ep/zksync/ZKSyncValidator.sol diff --git a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go deleted file mode 100644 index 192bf12f7f5..00000000000 --- a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go +++ /dev/null @@ -1,920 +0,0 @@ -package ccipreader - -import ( - "context" - "encoding/hex" - "math/big" - "sort" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient/simulated" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - "golang.org/x/exp/maps" - - readermocks "github.com/smartcontractkit/chainlink-ccip/mocks/pkg/contractreader" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - - "github.com/smartcontractkit/chainlink-common/pkg/codec" - "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_reader_tester" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - - "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - "github.com/smartcontractkit/chainlink-ccip/pkg/contractreader" - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - "github.com/smartcontractkit/chainlink-ccip/plugintypes" -) - -const ( - chainS1 = cciptypes.ChainSelector(1) - chainS2 = cciptypes.ChainSelector(2) - chainS3 = cciptypes.ChainSelector(3) - chainD = cciptypes.ChainSelector(4) -) - -var ( - defaultGasPrice = assets.GWei(10) - InitialLinkPrice = e18Mult(20) - InitialWethPrice = e18Mult(4000) - linkAddress = utils.RandomAddress() - wethAddress = utils.RandomAddress() -) - -func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { - ctx := testutils.Context(t) - - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameCommitReportAccepted}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameCommitReportAccepted: { - ChainSpecificName: consts.EventNameCommitReportAccepted, - ReadType: evmtypes.Event, - }, - }, - }, - }, - } - - sb, auth := setupSimulatedBackendAndAuth(t) - onRampAddress := utils.RandomAddress() - s := testSetup(ctx, t, chainD, chainD, nil, cfg, nil, map[cciptypes.ChainSelector][]types.BoundContract{ - chainS1: { - { - Address: onRampAddress.Hex(), - Name: consts.ContractNameOnRamp, - }, - }, - }, - true, - sb, - auth, - ) - - tokenA := common.HexToAddress("123") - const numReports = 5 - - var firstReportTs uint64 - for i := 0; i < numReports; i++ { - _, err := s.contract.EmitCommitReportAccepted(s.auth, ccip_reader_tester.OffRampCommitReport{ - PriceUpdates: ccip_reader_tester.InternalPriceUpdates{ - TokenPriceUpdates: []ccip_reader_tester.InternalTokenPriceUpdate{ - { - SourceToken: tokenA, - UsdPerToken: big.NewInt(1000), - }, - }, - GasPriceUpdates: []ccip_reader_tester.InternalGasPriceUpdate{ - { - DestChainSelector: uint64(chainD), - UsdPerUnitGas: big.NewInt(90), - }, - }, - }, - MerkleRoots: []ccip_reader_tester.InternalMerkleRoot{ - { - SourceChainSelector: uint64(chainS1), - MinSeqNr: 10, - MaxSeqNr: 20, - MerkleRoot: [32]byte{uint8(i) + 1}, //nolint:gosec // this won't overflow - OnRampAddress: common.LeftPadBytes(onRampAddress.Bytes(), 32), - }, - }, - RmnSignatures: []ccip_reader_tester.IRMNRemoteSignature{ - { - R: [32]byte{1}, - S: [32]byte{2}, - }, - { - R: [32]byte{3}, - S: [32]byte{4}, - }, - }, - }) - assert.NoError(t, err) - bh := s.sb.Commit() - b, err := s.sb.Client().BlockByHash(ctx, bh) - require.NoError(t, err) - if firstReportTs == 0 { - firstReportTs = b.Time() - } - } - - // Need to replay as sometimes the logs are not picked up by the log poller (?) - // Maybe another situation where chain reader doesn't register filters as expected. - require.NoError(t, s.lp.Replay(ctx, 1)) - - var reports []plugintypes.CommitPluginReportWithMeta - var err error - require.Eventually(t, func() bool { - reports, err = s.reader.CommitReportsGTETimestamp( - ctx, - chainD, - // Skips first report - //nolint:gosec // this won't overflow - time.Unix(int64(firstReportTs)+1, 0), - 10, - ) - require.NoError(t, err) - return len(reports) == numReports-1 - }, tests.WaitTimeout(t), 50*time.Millisecond) - - assert.Len(t, reports, numReports-1) - assert.Len(t, reports[0].Report.MerkleRoots, 1) - assert.Equal(t, chainS1, reports[0].Report.MerkleRoots[0].ChainSel) - assert.Equal(t, onRampAddress.Bytes(), []byte(reports[0].Report.MerkleRoots[0].OnRampAddress)) - assert.Equal(t, cciptypes.SeqNum(10), reports[0].Report.MerkleRoots[0].SeqNumsRange.Start()) - assert.Equal(t, cciptypes.SeqNum(20), reports[0].Report.MerkleRoots[0].SeqNumsRange.End()) - assert.Equal(t, "0x0200000000000000000000000000000000000000000000000000000000000000", - reports[0].Report.MerkleRoots[0].MerkleRoot.String()) - assert.Equal(t, tokenA.String(), string(reports[0].Report.PriceUpdates.TokenPriceUpdates[0].TokenID)) - assert.Equal(t, uint64(1000), reports[0].Report.PriceUpdates.TokenPriceUpdates[0].Price.Uint64()) - assert.Equal(t, chainD, reports[0].Report.PriceUpdates.GasPriceUpdates[0].ChainSel) - assert.Equal(t, uint64(90), reports[0].Report.PriceUpdates.GasPriceUpdates[0].GasPrice.Uint64()) -} - -func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { - ctx := testutils.Context(t) - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameExecutionStateChanged}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameExecutionStateChanged: { - ChainSpecificName: consts.EventNameExecutionStateChanged, - ReadType: evmtypes.Event, - EventDefinitions: &evmtypes.EventDefinitions{ - GenericTopicNames: map[string]string{ - "sourceChainSelector": consts.EventAttributeSourceChain, - "sequenceNumber": consts.EventAttributeSequenceNumber, - }, - GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ - consts.EventAttributeState: { - Name: "state", - }, - }, - }, - }, - }, - }, - }, - } - - sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, chainD, chainD, nil, cfg, nil, nil, true, sb, auth) - - _, err := s.contract.EmitExecutionStateChanged( - s.auth, - uint64(chainS1), - 14, - cciptypes.Bytes32{1, 0, 0, 1}, - cciptypes.Bytes32{1, 0, 0, 1, 1, 0, 0, 1}, - 1, - []byte{1, 2, 3, 4}, - big.NewInt(250_000), - ) - assert.NoError(t, err) - s.sb.Commit() - - _, err = s.contract.EmitExecutionStateChanged( - s.auth, - uint64(chainS1), - 15, - cciptypes.Bytes32{1, 0, 0, 2}, - cciptypes.Bytes32{1, 0, 0, 2, 1, 0, 0, 2}, - 1, - []byte{1, 2, 3, 4, 5}, - big.NewInt(350_000), - ) - assert.NoError(t, err) - s.sb.Commit() - - // Need to replay as sometimes the logs are not picked up by the log poller (?) - // Maybe another situation where chain reader doesn't register filters as expected. - require.NoError(t, s.lp.Replay(ctx, 1)) - - var executedRanges []cciptypes.SeqNumRange - require.Eventually(t, func() bool { - executedRanges, err = s.reader.ExecutedMessageRanges( - ctx, - chainS1, - chainD, - cciptypes.NewSeqNumRange(14, 15), - ) - require.NoError(t, err) - return len(executedRanges) == 2 - }, testutils.WaitTimeout(t), 50*time.Millisecond) - - assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].Start()) - assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].End()) - - assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].Start()) - assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].End()) -} - -func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { - ctx := testutils.Context(t) - - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOnRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameCCIPMessageSent}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameCCIPMessageSent: { - ChainSpecificName: "CCIPMessageSent", - ReadType: evmtypes.Event, - EventDefinitions: &evmtypes.EventDefinitions{ - GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ - consts.EventAttributeSourceChain: {Name: "message.header.sourceChainSelector"}, - consts.EventAttributeDestChain: {Name: "message.header.destChainSelector"}, - consts.EventAttributeSequenceNumber: {Name: "message.header.sequenceNumber"}, - }, - }, - OutputModifications: codec.ModifiersConfig{ - &codec.WrapperModifierConfig{Fields: map[string]string{ - "Message.FeeTokenAmount": "Int", - "Message.FeeValueJuels": "Int", - "Message.TokenAmounts.Amount": "Int", - }}, - }, - }, - }, - }, - }, - } - - sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, chainS1, chainD, nil, cfg, nil, nil, true, sb, auth) - - _, err := s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ - Header: ccip_reader_tester.InternalRampMessageHeader{ - MessageId: [32]byte{1, 0, 0, 0, 0}, - SourceChainSelector: uint64(chainS1), - DestChainSelector: uint64(chainD), - SequenceNumber: 10, - }, - Sender: utils.RandomAddress(), - Data: make([]byte, 0), - Receiver: utils.RandomAddress().Bytes(), - ExtraArgs: make([]byte, 0), - FeeToken: utils.RandomAddress(), - FeeTokenAmount: big.NewInt(1), - FeeValueJuels: big.NewInt(2), - TokenAmounts: []ccip_reader_tester.InternalEVM2AnyTokenTransfer{{Amount: big.NewInt(1)}, {Amount: big.NewInt(2)}}, - }) - assert.NoError(t, err) - - _, err = s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ - Header: ccip_reader_tester.InternalRampMessageHeader{ - MessageId: [32]byte{1, 0, 0, 0, 1}, - SourceChainSelector: uint64(chainS1), - DestChainSelector: uint64(chainD), - SequenceNumber: 15, - }, - Sender: utils.RandomAddress(), - Data: make([]byte, 0), - Receiver: utils.RandomAddress().Bytes(), - ExtraArgs: make([]byte, 0), - FeeToken: utils.RandomAddress(), - FeeTokenAmount: big.NewInt(3), - FeeValueJuels: big.NewInt(4), - TokenAmounts: []ccip_reader_tester.InternalEVM2AnyTokenTransfer{{Amount: big.NewInt(3)}, {Amount: big.NewInt(4)}}, - }) - assert.NoError(t, err) - - s.sb.Commit() - - // Need to replay as sometimes the logs are not picked up by the log poller (?) - // Maybe another situation where chain reader doesn't register filters as expected. - require.NoError(t, s.lp.Replay(ctx, 1)) - - var msgs []cciptypes.Message - require.Eventually(t, func() bool { - msgs, err = s.reader.MsgsBetweenSeqNums( - ctx, - chainS1, - cciptypes.NewSeqNumRange(5, 20), - ) - require.NoError(t, err) - return len(msgs) == 2 - }, tests.WaitTimeout(t), 100*time.Millisecond) - - require.Len(t, msgs, 2) - // sort to ensure ascending order of sequence numbers. - sort.Slice(msgs, func(i, j int) bool { - return msgs[i].Header.SequenceNumber < msgs[j].Header.SequenceNumber - }) - require.Equal(t, cciptypes.SeqNum(10), msgs[0].Header.SequenceNumber) - require.Equal(t, big.NewInt(1), msgs[0].FeeTokenAmount.Int) - require.Equal(t, big.NewInt(2), msgs[0].FeeValueJuels.Int) - require.Equal(t, int64(1), msgs[0].TokenAmounts[0].Amount.Int64()) - require.Equal(t, int64(2), msgs[0].TokenAmounts[1].Amount.Int64()) - - require.Equal(t, cciptypes.SeqNum(15), msgs[1].Header.SequenceNumber) - require.Equal(t, big.NewInt(3), msgs[1].FeeTokenAmount.Int) - require.Equal(t, big.NewInt(4), msgs[1].FeeValueJuels.Int) - require.Equal(t, int64(3), msgs[1].TokenAmounts[0].Amount.Int64()) - require.Equal(t, int64(4), msgs[1].TokenAmounts[1].Amount.Int64()) - - for _, msg := range msgs { - require.Equal(t, chainS1, msg.Header.SourceChainSelector) - require.Equal(t, chainD, msg.Header.DestChainSelector) - } -} - -func TestCCIPReader_NextSeqNum(t *testing.T) { - ctx := testutils.Context(t) - - onChainSeqNums := map[cciptypes.ChainSelector]cciptypes.SeqNum{ - chainS1: 10, - chainS2: 20, - chainS3: 30, - } - - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.MethodNameGetSourceChainConfig: { - ChainSpecificName: "getSourceChainConfig", - ReadType: evmtypes.Method, - }, - }, - }, - }, - } - - sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, chainD, chainD, onChainSeqNums, cfg, nil, nil, true, sb, auth) - - seqNums, err := s.reader.NextSeqNum(ctx, []cciptypes.ChainSelector{chainS1, chainS2, chainS3}) - assert.NoError(t, err) - assert.Len(t, seqNums, 3) - assert.Equal(t, cciptypes.SeqNum(10), seqNums[0]) - assert.Equal(t, cciptypes.SeqNum(20), seqNums[1]) - assert.Equal(t, cciptypes.SeqNum(30), seqNums[2]) -} - -func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) { - ctx := testutils.Context(t) - - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOnRamp: { - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.MethodNameGetExpectedNextSequenceNumber: { - ChainSpecificName: "getExpectedNextSequenceNumber", - ReadType: evmtypes.Method, - }, - }, - }, - }, - } - - sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, chainS1, chainD, nil, cfg, nil, nil, true, sb, auth) - - _, err := s.contract.SetDestChainSeqNr(s.auth, uint64(chainD), 10) - require.NoError(t, err) - s.sb.Commit() - - seqNum, err := s.reader.GetExpectedNextSequenceNumber(ctx, chainS1, chainD) - require.NoError(t, err) - require.Equal(t, cciptypes.SeqNum(10)+1, seqNum) - - _, err = s.contract.SetDestChainSeqNr(s.auth, uint64(chainD), 25) - require.NoError(t, err) - s.sb.Commit() - - seqNum, err = s.reader.GetExpectedNextSequenceNumber(ctx, chainS1, chainD) - require.NoError(t, err) - require.Equal(t, cciptypes.SeqNum(25)+1, seqNum) -} - -func TestCCIPReader_Nonces(t *testing.T) { - ctx := testutils.Context(t) - var nonces = map[cciptypes.ChainSelector]map[common.Address]uint64{ - chainS1: { - utils.RandomAddress(): 10, - utils.RandomAddress(): 20, - }, - chainS2: { - utils.RandomAddress(): 30, - utils.RandomAddress(): 40, - }, - chainS3: { - utils.RandomAddress(): 50, - utils.RandomAddress(): 60, - }, - } - - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameNonceManager: { - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.MethodNameGetInboundNonce: { - ChainSpecificName: "getInboundNonce", - ReadType: evmtypes.Method, - }, - }, - }, - }, - } - - sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, chainD, chainD, nil, cfg, nil, nil, true, sb, auth) - - // Add some nonces. - for chain, addrs := range nonces { - for addr, nonce := range addrs { - _, err := s.contract.SetInboundNonce(s.auth, uint64(chain), nonce, common.LeftPadBytes(addr.Bytes(), 32)) - assert.NoError(t, err) - } - } - s.sb.Commit() - - for sourceChain, addrs := range nonces { - var addrQuery []string - for addr := range addrs { - addrQuery = append(addrQuery, addr.String()) - } - addrQuery = append(addrQuery, utils.RandomAddress().String()) - - results, err := s.reader.Nonces(ctx, sourceChain, chainD, addrQuery) - assert.NoError(t, err) - assert.Len(t, results, len(addrQuery)) - for addr, nonce := range addrs { - assert.Equal(t, nonce, results[addr.String()]) - } - } -} - -func Test_GetChainFeePriceUpdates(t *testing.T) { - ctx := testutils.Context(t) - sb, auth := setupSimulatedBackendAndAuth(t) - feeQuoter := deployFeeQuoterWithPrices(t, auth, sb, chainS1) - - s := testSetup(ctx, t, chainD, chainD, nil, evmconfig.DestReaderConfig, - map[cciptypes.ChainSelector][]types.BoundContract{ - chainD: { - { - Address: feeQuoter.Address().String(), - Name: consts.ContractNameFeeQuoter, - }, - }, - }, - nil, - false, - sb, - auth, - ) - - updates := s.reader.GetChainFeePriceUpdate(ctx, []cciptypes.ChainSelector{chainS1, chainS2}) - // only chainS1 has a bound contract - require.Len(t, updates, 1) - require.Equal(t, defaultGasPrice.ToInt(), updates[chainS1].Value.Int) -} - -func Test_LinkPriceUSD(t *testing.T) { - ctx := testutils.Context(t) - sb, auth := setupSimulatedBackendAndAuth(t) - feeQuoter := deployFeeQuoterWithPrices(t, auth, sb, chainS1) - - s := testSetup(ctx, t, chainD, chainD, nil, evmconfig.DestReaderConfig, - map[cciptypes.ChainSelector][]types.BoundContract{ - chainD: { - { - Address: feeQuoter.Address().String(), - Name: consts.ContractNameFeeQuoter, - }, - }, - }, - nil, - false, - sb, - auth, - ) - - linkPriceUSD, err := s.reader.LinkPriceUSD(ctx) - require.NoError(t, err) - require.NotNil(t, linkPriceUSD.Int) - require.Equal(t, InitialLinkPrice, linkPriceUSD.Int) -} - -func Test_GetMedianDataAvailabilityGasConfig(t *testing.T) { - ctx := testutils.Context(t) - - sb, auth := setupSimulatedBackendAndAuth(t) - - // All fee quoters using same auth and simulated backend for simplicity - feeQuoter1 := deployFeeQuoterWithPrices(t, auth, sb, chainD) - feeQuoter2 := deployFeeQuoterWithPrices(t, auth, sb, chainD) - feeQuoter3 := deployFeeQuoterWithPrices(t, auth, sb, chainD) - feeQuoters := []*fee_quoter.FeeQuoter{feeQuoter1, feeQuoter2, feeQuoter3} - - // Update the dest chain config for each fee quoter - for i, fq := range feeQuoters { - destChainCfg := defaultFeeQuoterDestChainConfig() - //nolint:gosec // disable G115 - destChainCfg.DestDataAvailabilityOverheadGas = uint32(100 + i) - //nolint:gosec // disable G115 - destChainCfg.DestGasPerDataAvailabilityByte = uint16(200 + i) - //nolint:gosec // disable G115 - destChainCfg.DestDataAvailabilityMultiplierBps = uint16(1 + i) - _, err := fq.ApplyDestChainConfigUpdates(auth, []fee_quoter.FeeQuoterDestChainConfigArgs{ - { - DestChainSelector: uint64(chainD), - DestChainConfig: destChainCfg, - }, - }) - sb.Commit() - require.NoError(t, err) - } - - s := testSetup(ctx, t, chainD, chainD, nil, evmconfig.DestReaderConfig, map[cciptypes.ChainSelector][]types.BoundContract{ - chainS1: { - { - Address: feeQuoter1.Address().String(), - Name: consts.ContractNameFeeQuoter, - }, - }, - chainS2: { - { - Address: feeQuoter2.Address().String(), - Name: consts.ContractNameFeeQuoter, - }, - }, - chainS3: { - { - Address: feeQuoter3.Address().String(), - Name: consts.ContractNameFeeQuoter, - }, - }, - }, nil, - false, - sb, - auth, - ) - - daConfig, err := s.reader.GetMedianDataAvailabilityGasConfig(ctx) - require.NoError(t, err) - - // Verify the results - require.Equal(t, uint32(101), daConfig.DestDataAvailabilityOverheadGas) - require.Equal(t, uint16(201), daConfig.DestGasPerDataAvailabilityByte) - require.Equal(t, uint16(2), daConfig.DestDataAvailabilityMultiplierBps) -} - -func Test_GetWrappedNativeTokenPriceUSD(t *testing.T) { - ctx := testutils.Context(t) - sb, auth := setupSimulatedBackendAndAuth(t) - feeQuoter := deployFeeQuoterWithPrices(t, auth, sb, chainS1) - - // Mock the routerContract to return a native token address - routerContract := deployRouterWithNativeToken(t, auth, sb) - - s := testSetup(ctx, t, chainD, chainD, nil, evmconfig.DestReaderConfig, - map[cciptypes.ChainSelector][]types.BoundContract{ - chainD: { - { - Address: feeQuoter.Address().String(), - Name: consts.ContractNameFeeQuoter, - }, - { - Address: routerContract.Address().String(), - Name: consts.ContractNameRouter, - }, - }, - }, - nil, - false, - sb, - auth, - ) - - prices := s.reader.GetWrappedNativeTokenPriceUSD(ctx, []cciptypes.ChainSelector{chainD, chainS1}) - - // Only chainD has reader contracts bound - require.Len(t, prices, 1) - require.Equal(t, InitialWethPrice, prices[chainD].Int) -} - -func deployRouterWithNativeToken(t *testing.T, auth *bind.TransactOpts, sb *simulated.Backend) *router.Router { - address, _, _, err := router.DeployRouter( - auth, - sb.Client(), - wethAddress, - utils.RandomAddress(), // armProxy address - ) - require.NoError(t, err) - sb.Commit() - - routerContract, err := router.NewRouter(address, sb.Client()) - require.NoError(t, err) - - return routerContract -} - -func deployFeeQuoterWithPrices(t *testing.T, auth *bind.TransactOpts, sb *simulated.Backend, destChain cciptypes.ChainSelector) *fee_quoter.FeeQuoter { - address, _, _, err := fee_quoter.DeployFeeQuoter( - auth, - sb.Client(), - fee_quoter.FeeQuoterStaticConfig{ - MaxFeeJuelsPerMsg: big.NewInt(0).Mul(big.NewInt(2e2), big.NewInt(1e18)), - LinkToken: linkAddress, - TokenPriceStalenessThreshold: uint32(24 * 60 * 60), - }, - []common.Address{auth.From}, - []common.Address{wethAddress, linkAddress}, - []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, - []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, - []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{}, - []fee_quoter.FeeQuoterDestChainConfigArgs{ - { - - DestChainSelector: uint64(destChain), - DestChainConfig: defaultFeeQuoterDestChainConfig(), - }, - }, - ) - - require.NoError(t, err) - sb.Commit() - - feeQuoter, err := fee_quoter.NewFeeQuoter(address, sb.Client()) - require.NoError(t, err) - - _, err = feeQuoter.UpdatePrices( - auth, fee_quoter.InternalPriceUpdates{ - GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ - { - DestChainSelector: uint64(chainS1), - UsdPerUnitGas: defaultGasPrice.ToInt(), - }, - }, - TokenPriceUpdates: []fee_quoter.InternalTokenPriceUpdate{ - { - SourceToken: linkAddress, - UsdPerToken: InitialLinkPrice, - }, - { - SourceToken: wethAddress, - UsdPerToken: InitialWethPrice, - }, - }, - }, - ) - require.NoError(t, err) - sb.Commit() - - gas, err := feeQuoter.GetDestinationChainGasPrice(&bind.CallOpts{}, uint64(chainS1)) - require.NoError(t, err) - require.Equal(t, defaultGasPrice.ToInt(), gas.Value) - - return feeQuoter -} - -func defaultFeeQuoterDestChainConfig() fee_quoter.FeeQuoterDestChainConfig { - // https://github.com/smartcontractkit/ccip/blob/c4856b64bd766f1ddbaf5d13b42d3c4b12efde3a/contracts/src/v0.8/ccip/libraries/Internal.sol#L337-L337 - /* - ```Solidity - // bytes4(keccak256("CCIP ChainFamilySelector EVM")) - bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; - ``` - */ - evmFamilySelector, _ := hex.DecodeString("2812d52c") - return fee_quoter.FeeQuoterDestChainConfig{ - IsEnabled: true, - MaxNumberOfTokensPerMsg: 10, - MaxDataBytes: 256, - MaxPerMsgGasLimit: 3_000_000, - DestGasOverhead: 50_000, - DefaultTokenFeeUSDCents: 1, - DestGasPerPayloadByte: 10, - DestDataAvailabilityOverheadGas: 100, - DestGasPerDataAvailabilityByte: 100, - DestDataAvailabilityMultiplierBps: 1, - DefaultTokenDestGasOverhead: 125_000, - DefaultTxGasLimit: 200_000, - GasMultiplierWeiPerEth: 1, - NetworkFeeUSDCents: 1, - ChainFamilySelector: [4]byte(evmFamilySelector), - } -} - -func setupSimulatedBackendAndAuth(t *testing.T) (*simulated.Backend, *bind.TransactOpts) { - privateKey, err := crypto.GenerateKey() - require.NoError(t, err) - - blnc, ok := big.NewInt(0).SetString("999999999999999999999999999999999999", 10) - require.True(t, ok) - - alloc := map[common.Address]ethtypes.Account{crypto.PubkeyToAddress(privateKey.PublicKey): {Balance: blnc}} - simulatedBackend := simulated.NewBackend(alloc, simulated.WithBlockGasLimit(8000000)) - - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337)) - require.NoError(t, err) - auth.GasLimit = uint64(6000000) - - return simulatedBackend, auth -} - -func testSetup( - ctx context.Context, - t *testing.T, - readerChain, - destChain cciptypes.ChainSelector, - onChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum, - cfg evmtypes.ChainReaderConfig, - toBindContracts map[cciptypes.ChainSelector][]types.BoundContract, - toMockBindings map[cciptypes.ChainSelector][]types.BoundContract, - bindTester bool, - simulatedBackend *simulated.Backend, - auth *bind.TransactOpts, -) *testSetupData { - address, _, _, err := ccip_reader_tester.DeployCCIPReaderTester(auth, simulatedBackend.Client()) - assert.NoError(t, err) - simulatedBackend.Commit() - - // Setup contract client - contract, err := ccip_reader_tester.NewCCIPReaderTester(address, simulatedBackend.Client()) - assert.NoError(t, err) - - lggr := logger.TestLogger(t) - lggr.SetLogLevel(zapcore.ErrorLevel) - db := pgtest.NewSqlxDB(t) - t.Cleanup(func() { assert.NoError(t, db.Close()) }) - lpOpts := logpoller.Opts{ - PollPeriod: time.Millisecond, - FinalityDepth: 0, - BackfillBatchSize: 10, - RpcBatchSize: 10, - KeepFinalizedBlocksDepth: 100000, - } - cl := client.NewSimulatedBackendClient(t, simulatedBackend, big.NewInt(0).SetUint64(uint64(readerChain))) - headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(readerChain)), db, lggr), - cl, - lggr, - headTracker, - lpOpts, - ) - servicetest.Run(t, lp) - - for sourceChain, seqNum := range onChainSeqNums { - _, err1 := contract.SetSourceChainConfig(auth, uint64(sourceChain), ccip_reader_tester.OffRampSourceChainConfig{ - IsEnabled: true, - MinSeqNr: uint64(seqNum), - OnRamp: utils.RandomAddress().Bytes(), - }) - assert.NoError(t, err1) - simulatedBackend.Commit() - scc, err1 := contract.GetSourceChainConfig(&bind.CallOpts{Context: ctx}, uint64(sourceChain)) - assert.NoError(t, err1) - assert.Equal(t, seqNum, cciptypes.SeqNum(scc.MinSeqNr)) - } - - contractNames := maps.Keys(cfg.Contracts) - - cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, cfg) - require.NoError(t, err) - - extendedCr := contractreader.NewExtendedContractReader(cr) - - if bindTester { - err = extendedCr.Bind(ctx, []types.BoundContract{ - { - Address: address.String(), - Name: contractNames[0], - }, - }) - require.NoError(t, err) - } - - var otherCrs = make(map[cciptypes.ChainSelector]contractreader.Extended) - for chain, bindings := range toBindContracts { - cl2 := client.NewSimulatedBackendClient(t, simulatedBackend, big.NewInt(0).SetUint64(uint64(chain))) - headTracker2 := headtracker.NewSimulatedHeadTracker(cl2, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp2 := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(chain)), db, lggr), - cl2, - lggr, - headTracker2, - lpOpts, - ) - servicetest.Run(t, lp2) - - cr2, err2 := evm.NewChainReaderService(ctx, lggr, lp2, headTracker2, cl2, cfg) - require.NoError(t, err2) - - extendedCr2 := contractreader.NewExtendedContractReader(cr2) - err2 = extendedCr2.Bind(ctx, bindings) - require.NoError(t, err2) - otherCrs[chain] = extendedCr2 - } - - for chain, bindings := range toMockBindings { - if _, ok := otherCrs[chain]; ok { - require.False(t, ok, "chain %d already exists", chain) - } - m := readermocks.NewMockContractReaderFacade(t) - m.EXPECT().Bind(ctx, bindings).Return(nil) - ecr := contractreader.NewExtendedContractReader(m) - err = ecr.Bind(ctx, bindings) - require.NoError(t, err) - otherCrs[chain] = ecr - } - - servicetest.Run(t, cr) - - contractReaders := map[cciptypes.ChainSelector]contractreader.Extended{readerChain: extendedCr} - for chain, cr := range otherCrs { - contractReaders[chain] = cr - } - contractWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) - reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, destChain, nil) - - return &testSetupData{ - contractAddr: address, - contract: contract, - sb: simulatedBackend, - auth: auth, - lp: lp, - cl: cl, - reader: reader, - extendedCR: extendedCr, - } -} - -type testSetupData struct { - contractAddr common.Address - contract *ccip_reader_tester.CCIPReaderTester - sb *simulated.Backend - auth *bind.TransactOpts - lp logpoller.LogPoller - cl client.Client - reader ccipreaderpkg.CCIPReader - extendedCR contractreader.Extended -} - -func uBigInt(i uint64) *big.Int { - return new(big.Int).SetUint64(i) -} - -func e18Mult(amount uint64) *big.Int { - return new(big.Int).Mul(uBigInt(amount), uBigInt(1e18)) -} diff --git a/core/capabilities/ccip/ccipevm/encodingUtilsAbi.json b/core/capabilities/ccip/ccipevm/encodingUtilsAbi.json new file mode 100644 index 00000000000..4ebb363bffe --- /dev/null +++ b/core/capabilities/ccip/ccipevm/encodingUtilsAbi.json @@ -0,0 +1 @@ +[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DoNotDeploy","type":"error"},{"inputs":[{"internalType":"bytes32","name":"rmnReportVersion","type":"bytes32"},{"components":[{"internalType":"uint256","name":"destChainId","type":"uint256"},{"internalType":"uint64","name":"destChainSelector","type":"uint64"},{"internalType":"address","name":"rmnRemoteContractAddress","type":"address"},{"internalType":"address","name":"offrampAddress","type":"address"},{"internalType":"bytes32","name":"rmnHomeContractConfigDigest","type":"bytes32"},{"components":[{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"bytes","name":"onRampAddress","type":"bytes"},{"internalType":"uint64","name":"minSeqNr","type":"uint64"},{"internalType":"uint64","name":"maxSeqNr","type":"uint64"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"internalType":"struct Internal.MerkleRoot[]","name":"destLaneUpdates","type":"tuple[]"}],"internalType":"struct RMNRemote.Report","name":"rmnReport","type":"tuple"}],"name":"_rmnReport","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/core/capabilities/ccip/ccipevm/rmncrypto.go b/core/capabilities/ccip/ccipevm/rmncrypto.go index 1b97f5cc3bb..37b909dabe2 100644 --- a/core/capabilities/ccip/ccipevm/rmncrypto.go +++ b/core/capabilities/ccip/ccipevm/rmncrypto.go @@ -3,6 +3,7 @@ package ccipevm import ( "bytes" "context" + _ "embed" "errors" "fmt" "math/big" @@ -18,8 +19,10 @@ import ( // encodingUtilsAbi is the ABI for the EncodingUtils contract. // Should be imported when gethwrappers are moved from ccip repo to core. -// nolint:lll -const encodingUtilsAbiRaw = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DoNotDeploy","type":"error"},{"inputs":[{"internalType":"bytes32","name":"rmnReportVersion","type":"bytes32"},{"components":[{"internalType":"uint256","name":"destChainId","type":"uint256"},{"internalType":"uint64","name":"destChainSelector","type":"uint64"},{"internalType":"address","name":"rmnRemoteContractAddress","type":"address"},{"internalType":"address","name":"offrampAddress","type":"address"},{"internalType":"bytes32","name":"rmnHomeContractConfigDigest","type":"bytes32"},{"components":[{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"bytes","name":"onRampAddress","type":"bytes"},{"internalType":"uint64","name":"minSeqNr","type":"uint64"},{"internalType":"uint64","name":"maxSeqNr","type":"uint64"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"internalType":"struct Internal.MerkleRoot[]","name":"destLaneUpdates","type":"tuple[]"}],"internalType":"struct RMNRemote.Report","name":"rmnReport","type":"tuple"}],"name":"_rmnReport","outputs":[],"stateMutability":"nonpayable","type":"function"}]` +// +//go:embed encodingUtilsAbi.json +var encodingUtilsAbiRaw string + const addressEncodeAbiRaw = `[{"name":"method","type":"function","inputs":[{"name": "", "type": "address"}]}]` var ( diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index d3ca35bbe83..e89acac7baa 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -13,18 +13,23 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/consts" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" ) -type ToCalldataFunc func(rawReportCtx [3][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any +type ToCalldataFunc func(rawReportCtx [2][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any -func ToCommitCalldata(rawReportCtx [3][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any { +func ToCommitCalldata(rawReportCtx [2][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any { // Note that the name of the struct field is very important, since the encoder used // by the chainwriter uses mapstructure, which will use the struct field name to map // to the argument name in the function call. // If, for whatever reason, we want to change the field name, make sure to add a `mapstructure:""` tag // for that field. + + // WARNING: Be careful if you change the data types. + // Using a different type e.g. `type Foo [32]byte` instead of `[32]byte` + // will trigger undefined chainWriter behavior, e.g. transactions submitted with wrong arguments. return struct { - ReportContext [3][32]byte + ReportContext [2][32]byte Report []byte Rs [][32]byte Ss [][32]byte @@ -38,14 +43,18 @@ func ToCommitCalldata(rawReportCtx [3][32]byte, report []byte, rs, ss [][32]byte } } -func ToExecCalldata(rawReportCtx [3][32]byte, report []byte, _, _ [][32]byte, _ [32]byte) any { +func ToExecCalldata(rawReportCtx [2][32]byte, report []byte, _, _ [][32]byte, _ [32]byte) any { // Note that the name of the struct field is very important, since the encoder used // by the chainwriter uses mapstructure, which will use the struct field name to map // to the argument name in the function call. // If, for whatever reason, we want to change the field name, make sure to add a `mapstructure:""` tag // for that field. + + // WARNING: Be careful if you change the data types. + // Using a different type e.g. `type Foo [32]byte` instead of `[32]byte` + // will trigger undefined chainWriter behavior, e.g. transactions submitted with wrong arguments. return struct { - ReportContext [3][32]byte + ReportContext [2][32]byte Report []byte }{ ReportContext: rawReportCtx, @@ -56,7 +65,7 @@ func ToExecCalldata(rawReportCtx [3][32]byte, report []byte, _, _ [][32]byte, _ var _ ocr3types.ContractTransmitter[[]byte] = &commitTransmitter[[]byte]{} type commitTransmitter[RI any] struct { - cw commontypes.ChainWriter + cw commontypes.ContractWriter fromAccount ocrtypes.Account contractName string method string @@ -65,7 +74,7 @@ type commitTransmitter[RI any] struct { } func XXXNewContractTransmitterTestsOnly[RI any]( - cw commontypes.ChainWriter, + cw commontypes.ContractWriter, fromAccount ocrtypes.Account, contractName string, method string, @@ -83,7 +92,7 @@ func XXXNewContractTransmitterTestsOnly[RI any]( } func NewCommitContractTransmitter[RI any]( - cw commontypes.ChainWriter, + cw commontypes.ContractWriter, fromAccount ocrtypes.Account, offrampAddress string, ) ocr3types.ContractTransmitter[RI] { @@ -98,7 +107,7 @@ func NewCommitContractTransmitter[RI any]( } func NewExecContractTransmitter[RI any]( - cw commontypes.ChainWriter, + cw commontypes.ContractWriter, fromAccount ocrtypes.Account, offrampAddress string, ) ocr3types.ContractTransmitter[RI] { @@ -144,22 +153,7 @@ func (c *commitTransmitter[RI]) Transmit( // report ctx for OCR3 consists of the following // reportContext[0]: ConfigDigest // reportContext[1]: 24 byte padding, 8 byte sequence number - // reportContext[2]: unused - // convert seqNum, which is a uint64, into a uint32 epoch and uint8 round - // while this does truncate the sequence number, it is not a problem because - // it still gives us 2^40 - 1 possible sequence numbers. - // assuming a sequence number is generated every second, this gives us - // 1099511627775 seconds, or approximately 34,865 years, before we run out - // of sequence numbers. - epoch, round := uint64ToUint32AndUint8(seqNr) - rawReportCtx := evmutil.RawReportContext(ocrtypes.ReportContext{ - ReportTimestamp: ocrtypes.ReportTimestamp{ - ConfigDigest: configDigest, - Epoch: epoch, - Round: round, - }, - // ExtraData not used in OCR3 - }) + rawReportCtx := ocr2key.RawReportContext3(configDigest, seqNr) if c.toCalldataFn == nil { return errors.New("toCalldataFn is nil") @@ -182,7 +176,3 @@ func (c *commitTransmitter[RI]) Transmit( return nil } - -func uint64ToUint32AndUint8(x uint64) (uint32, uint8) { - return uint32(x >> 32), uint8(x) -} diff --git a/core/capabilities/ccip/ocrimpls/keyring.go b/core/capabilities/ccip/ocrimpls/keyring.go index 4b15c75b09a..cd753810341 100644 --- a/core/capabilities/ccip/ocrimpls/keyring.go +++ b/core/capabilities/ccip/ocrimpls/keyring.go @@ -6,16 +6,26 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" ) +// OCR3SignerVerifierExtra is an extension of OCR3SignerVerifier that +// also exposes the public key and max signature length which are required by the ocr3Keyring adapter. +type OCR3SignerVerifierExtra interface { + ocr2key.OCR3SignerVerifier + PublicKey() types.OnchainPublicKey + MaxSignatureLength() int +} + var _ ocr3types.OnchainKeyring[[]byte] = &ocr3Keyring[[]byte]{} +// ocr3Keyring is an adapter that exposes ocr3 onchain keyring. type ocr3Keyring[RI any] struct { - core types.OnchainKeyring + core OCR3SignerVerifierExtra lggr logger.Logger } -func NewOnchainKeyring[RI any](keyring types.OnchainKeyring, lggr logger.Logger) *ocr3Keyring[RI] { +func NewOnchainKeyring[RI any](keyring OCR3SignerVerifierExtra, lggr logger.Logger) *ocr3Keyring[RI] { return &ocr3Keyring[RI]{ core: keyring, lggr: lggr.Named("OCR3Keyring"), @@ -31,31 +41,20 @@ func (w *ocr3Keyring[RI]) MaxSignatureLength() int { } func (w *ocr3Keyring[RI]) Sign(configDigest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[RI]) (signature []byte, err error) { - epoch, round := uint64ToUint32AndUint8(seqNr) - rCtx := types.ReportContext{ - ReportTimestamp: types.ReportTimestamp{ - ConfigDigest: configDigest, - Epoch: epoch, - Round: round, - }, - } - - w.lggr.Debugw("signing report", "configDigest", configDigest.Hex(), "seqNr", seqNr, "report", hexutil.Encode(r.Report)) - - return w.core.Sign(rCtx, r.Report) + w.lggr.Debugw( + "signing report", + "configDigest", configDigest.Hex(), + "seqNr", seqNr, + "report", hexutil.Encode(r.Report), + ) + return w.core.Sign3(configDigest, seqNr, r.Report) } func (w *ocr3Keyring[RI]) Verify(key types.OnchainPublicKey, configDigest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[RI], signature []byte) bool { - epoch, round := uint64ToUint32AndUint8(seqNr) - rCtx := types.ReportContext{ - ReportTimestamp: types.ReportTimestamp{ - ConfigDigest: configDigest, - Epoch: epoch, - Round: round, - }, - } - - w.lggr.Debugw("verifying report", "configDigest", configDigest.Hex(), "seqNr", seqNr, "report", hexutil.Encode(r.Report)) - - return w.core.Verify(key, rCtx, r.Report, signature) + w.lggr.Debugw("verifying report", + "configDigest", configDigest.Hex(), + "seqNr", seqNr, + "report", hexutil.Encode(r.Report), + ) + return w.core.Verify3(key, configDigest, seqNr, r.Report, signature) } diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index a5063eb8d1c..a716d96418a 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -22,6 +22,7 @@ import ( cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr3/promwrapper" "github.com/smartcontractkit/libocr/commontypes" libocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus" @@ -222,13 +223,19 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( config cctypes.OCR3ConfigWithMeta, destRelayID types.RelayID, contractReaders map[cciptypes.ChainSelector]types.ContractReader, - chainWriters map[cciptypes.ChainSelector]types.ChainWriter, - destChainWriter types.ChainWriter, + chainWriters map[cciptypes.ChainSelector]types.ContractWriter, + destChainWriter types.ContractWriter, destFromAccounts []string, publicConfig ocr3confighelper.PublicConfig, ) (ocr3types.ReportingPluginFactory[[]byte], ocr3types.ContractTransmitter[[]byte], error) { var factory ocr3types.ReportingPluginFactory[[]byte] var transmitter ocr3types.ContractTransmitter[[]byte] + + chainID, err := chainsel.GetChainIDFromSelector(uint64(config.Config.ChainSelector)) + if err != nil { + return nil, nil, fmt.Errorf("unsupported chain selector %d %w", config.Config.ChainSelector, err) + } + if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) { if !i.peerWrapper.IsStarted() { return nil, nil, fmt.Errorf("peer wrapper is not started") @@ -263,6 +270,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( rmnPeerClient, rmnCrypto, ) + factory = promwrapper.NewReportingPluginFactory[[]byte](factory, i.lggr, chainID, "CCIPCommit") transmitter = ocrimpls.NewCommitContractTransmitter[[]byte](destChainWriter, ocrtypes.Account(destFromAccounts[0]), hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? @@ -283,6 +291,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( contractReaders, chainWriters, ) + factory = promwrapper.NewReportingPluginFactory[[]byte](factory, i.lggr, chainID, "CCIPExec") transmitter = ocrimpls.NewExecContractTransmitter[[]byte](destChainWriter, ocrtypes.Account(destFromAccounts[0]), hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? @@ -299,10 +308,10 @@ func (i *pluginOracleCreator) createReadersAndWriters( pluginType cctypes.PluginType, config cctypes.OCR3ConfigWithMeta, publicCfg ocr3confighelper.PublicConfig, - chainFamily string, + destChainFamily string, ) ( map[cciptypes.ChainSelector]types.ContractReader, - map[cciptypes.ChainSelector]types.ChainWriter, + map[cciptypes.ChainSelector]types.ContractWriter, error, ) { ofc, err := decodeAndValidateOffchainConfig(pluginType, publicCfg) @@ -325,11 +334,11 @@ func (i *pluginOracleCreator) createReadersAndWriters( } contractReaders := make(map[cciptypes.ChainSelector]types.ContractReader) - chainWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) + chainWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) for relayID, relayer := range i.relayers { chainID := relayID.ChainID - - chainSelector, err1 := i.getChainSelector(chainID, chainFamily) + relayChainFamily := relayID.Network + chainSelector, err1 := i.getChainSelector(chainID, relayChainFamily) if err1 != nil { return nil, nil, fmt.Errorf("failed to get chain selector from chain ID %s: %w", chainID, err1) } @@ -344,7 +353,7 @@ func (i *pluginOracleCreator) createReadersAndWriters( return nil, nil, err1 } - if chainID == destChainID { + if chainID == destChainID && destChainFamily == relayChainFamily { offrampAddressHex := common.BytesToAddress(config.Config.OfframpAddress).Hex() err2 := cr.Bind(ctx, []types.BoundContract{ { @@ -367,7 +376,7 @@ func (i *pluginOracleCreator) createReadersAndWriters( relayer, i.transmitters, execBatchGasLimit, - chainFamily) + relayChainFamily) if err1 != nil { return nil, nil, err1 } @@ -481,7 +490,7 @@ func createChainWriter( transmitters map[types.RelayID][]string, execBatchGasLimit uint64, chainFamily string, -) (types.ChainWriter, error) { +) (types.ContractWriter, error) { var fromAddress common.Address transmitter, ok := transmitters[types.NewRelayID(chainFamily, chainID)] if ok { @@ -503,7 +512,7 @@ func createChainWriter( return nil, fmt.Errorf("failed to marshal chain writer config: %w", err) } - cw, err := relayer.NewChainWriter(ctx, chainWriterConfig) + cw, err := relayer.NewContractWriter(ctx, chainWriterConfig) if err != nil { return nil, fmt.Errorf("failed to create chain writer for chain %s: %w", chainID, err) } diff --git a/core/capabilities/compute/compute.go b/core/capabilities/compute/compute.go index 32e43e8d62e..316e4f00eea 100644 --- a/core/capabilities/compute/compute.go +++ b/core/capabilities/compute/compute.go @@ -273,9 +273,19 @@ func (c *Compute) worker(ctx context.Context) { } func (c *Compute) Close() error { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + c.modules.close() close(c.stopCh) + + err := c.registry.Remove(ctx, CapabilityIDCompute) + if err != nil { + return err + } + c.wg.Wait() + return nil } diff --git a/core/capabilities/don_notifier.go b/core/capabilities/don_notifier.go new file mode 100644 index 00000000000..4edb38d3661 --- /dev/null +++ b/core/capabilities/don_notifier.go @@ -0,0 +1,43 @@ +package capabilities + +import ( + "context" + "sync" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" +) + +type DonNotifier struct { + mu sync.Mutex + don capabilities.DON + notified bool + ch chan struct{} +} + +func NewDonNotifier() *DonNotifier { + return &DonNotifier{ + ch: make(chan struct{}), + } +} + +func (n *DonNotifier) NotifyDonSet(don capabilities.DON) { + n.mu.Lock() + defer n.mu.Unlock() + if !n.notified { + n.don = don + n.notified = true + close(n.ch) + } +} + +func (n *DonNotifier) WaitForDon(ctx context.Context) (capabilities.DON, error) { + select { + case <-ctx.Done(): + return capabilities.DON{}, ctx.Err() + case <-n.ch: + } + <-n.ch + n.mu.Lock() + defer n.mu.Unlock() + return n.don, nil +} diff --git a/core/capabilities/don_notifier_test.go b/core/capabilities/don_notifier_test.go new file mode 100644 index 00000000000..f37931259ba --- /dev/null +++ b/core/capabilities/don_notifier_test.go @@ -0,0 +1,49 @@ +package capabilities_test + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities" +) + +func TestDonNotifier_WaitForDon(t *testing.T) { + notifier := capabilities.NewDonNotifier() + don := commoncap.DON{ + ID: 1, + } + + go func() { + time.Sleep(100 * time.Millisecond) + notifier.NotifyDonSet(don) + }() + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + + result, err := notifier.WaitForDon(ctx) + require.NoError(t, err) + assert.Equal(t, don, result) + + result, err = notifier.WaitForDon(ctx) + require.NoError(t, err) + assert.Equal(t, don, result) +} + +func TestDonNotifier_WaitForDon_ContextTimeout(t *testing.T) { + notifier := capabilities.NewDonNotifier() + + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Millisecond) + defer cancel() + + _, err := notifier.WaitForDon(ctx) + require.Error(t, err) + assert.Equal(t, context.DeadlineExceeded, err) +} diff --git a/core/capabilities/integration_tests/keystone/setup.go b/core/capabilities/integration_tests/keystone/setup.go index b9b98baaf7e..f4b29323537 100644 --- a/core/capabilities/integration_tests/keystone/setup.go +++ b/core/capabilities/integration_tests/keystone/setup.go @@ -130,7 +130,7 @@ func newReport(t *testing.T, feedID [32]byte, price *big.Int, timestamp int64) [ v3Codec := reportcodec.NewReportCodec(feedID, logger.TestLogger(t)) raw, err := v3Codec.BuildReport(ctx, v3.ReportFields{ BenchmarkPrice: price, - //nolint:gosec // disable G115 + Timestamp: uint32(timestamp), Bid: big.NewInt(0), Ask: big.NewInt(0), diff --git a/core/capabilities/launcher.go b/core/capabilities/launcher.go index be06dcf60c1..27c43fe0a53 100644 --- a/core/capabilities/launcher.go +++ b/core/capabilities/launcher.go @@ -43,11 +43,12 @@ var defaultStreamConfig = p2ptypes.StreamConfig{ type launcher struct { services.StateMachine - lggr logger.Logger - peerWrapper p2ptypes.PeerWrapper - dispatcher remotetypes.Dispatcher - registry *Registry - subServices []services.Service + lggr logger.Logger + peerWrapper p2ptypes.PeerWrapper + dispatcher remotetypes.Dispatcher + registry *Registry + subServices []services.Service + workflowDonNotifier donNotifier } func unmarshalCapabilityConfig(data []byte) (capabilities.CapabilityConfiguration, error) { @@ -86,18 +87,24 @@ func unmarshalCapabilityConfig(data []byte) (capabilities.CapabilityConfiguratio }, nil } +type donNotifier interface { + NotifyDonSet(don capabilities.DON) +} + func NewLauncher( lggr logger.Logger, peerWrapper p2ptypes.PeerWrapper, dispatcher remotetypes.Dispatcher, registry *Registry, + workflowDonNotifier donNotifier, ) *launcher { return &launcher{ - lggr: lggr.Named("CapabilitiesLauncher"), - peerWrapper: peerWrapper, - dispatcher: dispatcher, - registry: registry, - subServices: []services.Service{}, + lggr: lggr.Named("CapabilitiesLauncher"), + peerWrapper: peerWrapper, + dispatcher: dispatcher, + registry: registry, + subServices: []services.Service{}, + workflowDonNotifier: workflowDonNotifier, } } @@ -128,6 +135,7 @@ func (w *launcher) Name() string { } func (w *launcher) Launch(ctx context.Context, state *registrysyncer.LocalRegistry) error { + w.lggr.Debug("CapabilitiesLauncher triggered...") w.registry.SetLocalRegistry(state) allDONIDs := []registrysyncer.DonID{} @@ -215,6 +223,9 @@ func (w *launcher) Launch(ctx context.Context, state *registrysyncer.LocalRegist return errors.New("invariant violation: node is part of more than one workflowDON") } + w.lggr.Debug("Notifying DON set...") + w.workflowDonNotifier.NotifyDonSet(myDON.DON) + for _, rcd := range remoteCapabilityDONs { err := w.addRemoteCapabilities(ctx, myDON, rcd, state) if err != nil { diff --git a/core/capabilities/launcher_test.go b/core/capabilities/launcher_test.go index 013463bfdbb..c130f9833d9 100644 --- a/core/capabilities/launcher_test.go +++ b/core/capabilities/launcher_test.go @@ -33,6 +33,12 @@ import ( var _ capabilities.TriggerCapability = (*mockTrigger)(nil) +type mockDonNotifier struct { +} + +func (m *mockDonNotifier) NotifyDonSet(don capabilities.DON) { +} + type mockTrigger struct { capabilities.CapabilityInfo } @@ -196,6 +202,7 @@ func TestLauncher(t *testing.T) { wrapper, dispatcher, registry, + &mockDonNotifier{}, ) dispatcher.On("SetReceiver", fullTriggerCapID, dID, mock.AnythingOfType("*remote.triggerPublisher")).Return(nil) @@ -305,6 +312,7 @@ func TestLauncher(t *testing.T) { wrapper, dispatcher, registry, + &mockDonNotifier{}, ) err = launcher.Launch(ctx, state) @@ -409,6 +417,7 @@ func TestLauncher(t *testing.T) { wrapper, dispatcher, registry, + &mockDonNotifier{}, ) err = launcher.Launch(ctx, state) @@ -600,6 +609,7 @@ func TestLauncher_RemoteTriggerModeAggregatorShim(t *testing.T) { wrapper, dispatcher, registry, + &mockDonNotifier{}, ) dispatcher.On("SetReceiver", fullTriggerCapID, capDonID, mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) @@ -752,6 +762,7 @@ func TestSyncer_IgnoresCapabilitiesForPrivateDON(t *testing.T) { wrapper, dispatcher, registry, + &mockDonNotifier{}, ) // If the DON were public, this would fail with two errors: @@ -917,6 +928,7 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDON(t *testing.T) { wrapper, dispatcher, registry, + &mockDonNotifier{}, ) dispatcher.On("SetReceiver", fullTriggerCapID, capDonID, mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) @@ -1082,6 +1094,7 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDONButIgnoresPrivateCapabilitie wrapper, dispatcher, registry, + &mockDonNotifier{}, ) dispatcher.On("SetReceiver", fullTriggerCapID, triggerCapDonID, mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) @@ -1232,6 +1245,7 @@ func TestLauncher_SucceedsEvenIfDispatcherAlreadyHasReceiver(t *testing.T) { wrapper, dispatcher, registry, + &mockDonNotifier{}, ) err = launcher.Launch(ctx, state) diff --git a/core/capabilities/registry.go b/core/capabilities/registry.go index 47285505805..7038dcdb4b7 100644 --- a/core/capabilities/registry.go +++ b/core/capabilities/registry.go @@ -193,6 +193,21 @@ func (r *Registry) Add(ctx context.Context, c capabilities.BaseCapability) error return nil } +// Add adds a capability to the registry. +func (r *Registry) Remove(ctx context.Context, id string) error { + r.mu.Lock() + defer r.mu.Unlock() + + _, ok := r.m[id] + if !ok { + return fmt.Errorf("unable to remove, capability not found: %s", id) + } + + delete(r.m, id) + r.lggr.Infow("capability removed", "id", id) + return nil +} + // NewRegistry returns a new Registry. func NewRegistry(lggr logger.Logger) *Registry { return &Registry{ diff --git a/core/capabilities/remote/executable/endtoend_test.go b/core/capabilities/remote/executable/endtoend_test.go index 376b4d5852f..4e78fead87e 100644 --- a/core/capabilities/remote/executable/endtoend_test.go +++ b/core/capabilities/remote/executable/endtoend_test.go @@ -63,60 +63,6 @@ func Test_RemoteExecutableCapability_TransmissionSchedules(t *testing.T) { testRemoteExecutableCapability(ctx, t, capability, 10, 9, timeOut, 10, 9, timeOut, method) } -func Test_RemoteExecutionCapability_DonTopologies(t *testing.T) { - ctx := testutils.Context(t) - - responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { - require.NoError(t, responseError) - mp, err := response.Value.Unwrap() - require.NoError(t, err) - assert.Equal(t, "aValue1", mp.(map[string]any)["response"].(string)) - } - - transmissionSchedule, err := values.NewMap(map[string]any{ - "schedule": transmission.Schedule_OneAtATime, - "deltaStage": "10ms", - }) - require.NoError(t, err) - - timeOut := 10 * time.Minute - - capability := &TestCapability{} - - var methods []func(ctx context.Context, caller commoncap.ExecutableCapability) - - methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { - executeCapability(ctx, t, caller, transmissionSchedule, responseTest) - }) - - methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { - registerWorkflow(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseError error) { - require.NoError(t, responseError) - }) - }) - - methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { - unregisterWorkflow(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseError error) { - require.NoError(t, responseError) - }) - }) - - for _, method := range methods { - // Test scenarios where the number of submissions is greater than or equal to F + 1 - testRemoteExecutableCapability(ctx, t, capability, 1, 0, timeOut, 1, 0, timeOut, method) - testRemoteExecutableCapability(ctx, t, capability, 4, 3, timeOut, 1, 0, timeOut, method) - testRemoteExecutableCapability(ctx, t, capability, 10, 3, timeOut, 1, 0, timeOut, method) - - testRemoteExecutableCapability(ctx, t, capability, 1, 0, timeOut, 1, 0, timeOut, method) - testRemoteExecutableCapability(ctx, t, capability, 1, 0, timeOut, 4, 3, timeOut, method) - testRemoteExecutableCapability(ctx, t, capability, 1, 0, timeOut, 10, 3, timeOut, method) - - testRemoteExecutableCapability(ctx, t, capability, 4, 3, timeOut, 4, 3, timeOut, method) - testRemoteExecutableCapability(ctx, t, capability, 10, 3, timeOut, 10, 3, timeOut, method) - testRemoteExecutableCapability(ctx, t, capability, 10, 9, timeOut, 10, 9, timeOut, method) - } -} - func Test_RemoteExecutionCapability_CapabilityError(t *testing.T) { ctx := testutils.Context(t) diff --git a/core/capabilities/targets/mocks/chain_writer.go b/core/capabilities/targets/mocks/chain_writer.go deleted file mode 100644 index 5d7102fd4df..00000000000 --- a/core/capabilities/targets/mocks/chain_writer.go +++ /dev/null @@ -1,435 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package mocks - -import ( - context "context" - big "math/big" - - mock "github.com/stretchr/testify/mock" - - types "github.com/smartcontractkit/chainlink-common/pkg/types" -) - -// ChainWriter is an autogenerated mock type for the ChainWriter type -type ChainWriter struct { - mock.Mock -} - -type ChainWriter_Expecter struct { - mock *mock.Mock -} - -func (_m *ChainWriter) EXPECT() *ChainWriter_Expecter { - return &ChainWriter_Expecter{mock: &_m.Mock} -} - -// Close provides a mock function with given fields: -func (_m *ChainWriter) Close() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Close") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ChainWriter_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type ChainWriter_Close_Call struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *ChainWriter_Expecter) Close() *ChainWriter_Close_Call { - return &ChainWriter_Close_Call{Call: _e.mock.On("Close")} -} - -func (_c *ChainWriter_Close_Call) Run(run func()) *ChainWriter_Close_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainWriter_Close_Call) Return(_a0 error) *ChainWriter_Close_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainWriter_Close_Call) RunAndReturn(run func() error) *ChainWriter_Close_Call { - _c.Call.Return(run) - return _c -} - -// GetFeeComponents provides a mock function with given fields: ctx -func (_m *ChainWriter) GetFeeComponents(ctx context.Context) (*types.ChainFeeComponents, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for GetFeeComponents") - } - - var r0 *types.ChainFeeComponents - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*types.ChainFeeComponents, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) *types.ChainFeeComponents); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ChainFeeComponents) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ChainWriter_GetFeeComponents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeeComponents' -type ChainWriter_GetFeeComponents_Call struct { - *mock.Call -} - -// GetFeeComponents is a helper method to define mock.On call -// - ctx context.Context -func (_e *ChainWriter_Expecter) GetFeeComponents(ctx interface{}) *ChainWriter_GetFeeComponents_Call { - return &ChainWriter_GetFeeComponents_Call{Call: _e.mock.On("GetFeeComponents", ctx)} -} - -func (_c *ChainWriter_GetFeeComponents_Call) Run(run func(ctx context.Context)) *ChainWriter_GetFeeComponents_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *ChainWriter_GetFeeComponents_Call) Return(_a0 *types.ChainFeeComponents, _a1 error) *ChainWriter_GetFeeComponents_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ChainWriter_GetFeeComponents_Call) RunAndReturn(run func(context.Context) (*types.ChainFeeComponents, error)) *ChainWriter_GetFeeComponents_Call { - _c.Call.Return(run) - return _c -} - -// GetTransactionStatus provides a mock function with given fields: ctx, transactionID -func (_m *ChainWriter) GetTransactionStatus(ctx context.Context, transactionID string) (types.TransactionStatus, error) { - ret := _m.Called(ctx, transactionID) - - if len(ret) == 0 { - panic("no return value specified for GetTransactionStatus") - } - - var r0 types.TransactionStatus - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (types.TransactionStatus, error)); ok { - return rf(ctx, transactionID) - } - if rf, ok := ret.Get(0).(func(context.Context, string) types.TransactionStatus); ok { - r0 = rf(ctx, transactionID) - } else { - r0 = ret.Get(0).(types.TransactionStatus) - } - - if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, transactionID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ChainWriter_GetTransactionStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTransactionStatus' -type ChainWriter_GetTransactionStatus_Call struct { - *mock.Call -} - -// GetTransactionStatus is a helper method to define mock.On call -// - ctx context.Context -// - transactionID string -func (_e *ChainWriter_Expecter) GetTransactionStatus(ctx interface{}, transactionID interface{}) *ChainWriter_GetTransactionStatus_Call { - return &ChainWriter_GetTransactionStatus_Call{Call: _e.mock.On("GetTransactionStatus", ctx, transactionID)} -} - -func (_c *ChainWriter_GetTransactionStatus_Call) Run(run func(ctx context.Context, transactionID string)) *ChainWriter_GetTransactionStatus_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string)) - }) - return _c -} - -func (_c *ChainWriter_GetTransactionStatus_Call) Return(_a0 types.TransactionStatus, _a1 error) *ChainWriter_GetTransactionStatus_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ChainWriter_GetTransactionStatus_Call) RunAndReturn(run func(context.Context, string) (types.TransactionStatus, error)) *ChainWriter_GetTransactionStatus_Call { - _c.Call.Return(run) - return _c -} - -// HealthReport provides a mock function with given fields: -func (_m *ChainWriter) HealthReport() map[string]error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for HealthReport") - } - - var r0 map[string]error - if rf, ok := ret.Get(0).(func() map[string]error); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]error) - } - } - - return r0 -} - -// ChainWriter_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' -type ChainWriter_HealthReport_Call struct { - *mock.Call -} - -// HealthReport is a helper method to define mock.On call -func (_e *ChainWriter_Expecter) HealthReport() *ChainWriter_HealthReport_Call { - return &ChainWriter_HealthReport_Call{Call: _e.mock.On("HealthReport")} -} - -func (_c *ChainWriter_HealthReport_Call) Run(run func()) *ChainWriter_HealthReport_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainWriter_HealthReport_Call) Return(_a0 map[string]error) *ChainWriter_HealthReport_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainWriter_HealthReport_Call) RunAndReturn(run func() map[string]error) *ChainWriter_HealthReport_Call { - _c.Call.Return(run) - return _c -} - -// Name provides a mock function with given fields: -func (_m *ChainWriter) Name() string { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Name") - } - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// ChainWriter_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' -type ChainWriter_Name_Call struct { - *mock.Call -} - -// Name is a helper method to define mock.On call -func (_e *ChainWriter_Expecter) Name() *ChainWriter_Name_Call { - return &ChainWriter_Name_Call{Call: _e.mock.On("Name")} -} - -func (_c *ChainWriter_Name_Call) Run(run func()) *ChainWriter_Name_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainWriter_Name_Call) Return(_a0 string) *ChainWriter_Name_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainWriter_Name_Call) RunAndReturn(run func() string) *ChainWriter_Name_Call { - _c.Call.Return(run) - return _c -} - -// Ready provides a mock function with given fields: -func (_m *ChainWriter) Ready() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Ready") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ChainWriter_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' -type ChainWriter_Ready_Call struct { - *mock.Call -} - -// Ready is a helper method to define mock.On call -func (_e *ChainWriter_Expecter) Ready() *ChainWriter_Ready_Call { - return &ChainWriter_Ready_Call{Call: _e.mock.On("Ready")} -} - -func (_c *ChainWriter_Ready_Call) Run(run func()) *ChainWriter_Ready_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainWriter_Ready_Call) Return(_a0 error) *ChainWriter_Ready_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainWriter_Ready_Call) RunAndReturn(run func() error) *ChainWriter_Ready_Call { - _c.Call.Return(run) - return _c -} - -// Start provides a mock function with given fields: _a0 -func (_m *ChainWriter) Start(_a0 context.Context) error { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for Start") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ChainWriter_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' -type ChainWriter_Start_Call struct { - *mock.Call -} - -// Start is a helper method to define mock.On call -// - _a0 context.Context -func (_e *ChainWriter_Expecter) Start(_a0 interface{}) *ChainWriter_Start_Call { - return &ChainWriter_Start_Call{Call: _e.mock.On("Start", _a0)} -} - -func (_c *ChainWriter_Start_Call) Run(run func(_a0 context.Context)) *ChainWriter_Start_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *ChainWriter_Start_Call) Return(_a0 error) *ChainWriter_Start_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainWriter_Start_Call) RunAndReturn(run func(context.Context) error) *ChainWriter_Start_Call { - _c.Call.Return(run) - return _c -} - -// SubmitTransaction provides a mock function with given fields: ctx, contractName, method, args, transactionID, toAddress, meta, value -func (_m *ChainWriter) SubmitTransaction(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int) error { - ret := _m.Called(ctx, contractName, method, args, transactionID, toAddress, meta, value) - - if len(ret) == 0 { - panic("no return value specified for SubmitTransaction") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error); ok { - r0 = rf(ctx, contractName, method, args, transactionID, toAddress, meta, value) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ChainWriter_SubmitTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubmitTransaction' -type ChainWriter_SubmitTransaction_Call struct { - *mock.Call -} - -// SubmitTransaction is a helper method to define mock.On call -// - ctx context.Context -// - contractName string -// - method string -// - args any -// - transactionID string -// - toAddress string -// - meta *types.TxMeta -// - value *big.Int -func (_e *ChainWriter_Expecter) SubmitTransaction(ctx interface{}, contractName interface{}, method interface{}, args interface{}, transactionID interface{}, toAddress interface{}, meta interface{}, value interface{}) *ChainWriter_SubmitTransaction_Call { - return &ChainWriter_SubmitTransaction_Call{Call: _e.mock.On("SubmitTransaction", ctx, contractName, method, args, transactionID, toAddress, meta, value)} -} - -func (_c *ChainWriter_SubmitTransaction_Call) Run(run func(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int)) *ChainWriter_SubmitTransaction_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(any), args[4].(string), args[5].(string), args[6].(*types.TxMeta), args[7].(*big.Int)) - }) - return _c -} - -func (_c *ChainWriter_SubmitTransaction_Call) Return(_a0 error) *ChainWriter_SubmitTransaction_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainWriter_SubmitTransaction_Call) RunAndReturn(run func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error) *ChainWriter_SubmitTransaction_Call { - _c.Call.Return(run) - return _c -} - -// NewChainWriter creates a new instance of ChainWriter. 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 NewChainWriter(t interface { - mock.TestingT - Cleanup(func()) -}) *ChainWriter { - mock := &ChainWriter{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/capabilities/targets/mocks/contract_writer.go b/core/capabilities/targets/mocks/contract_writer.go new file mode 100644 index 00000000000..c6128e68fc7 --- /dev/null +++ b/core/capabilities/targets/mocks/contract_writer.go @@ -0,0 +1,435 @@ +// Code generated by mockery v2.46.3. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + mock "github.com/stretchr/testify/mock" + + types "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// ContractWriter is an autogenerated mock type for the ContractWriter type +type ContractWriter struct { + mock.Mock +} + +type ContractWriter_Expecter struct { + mock *mock.Mock +} + +func (_m *ContractWriter) EXPECT() *ContractWriter_Expecter { + return &ContractWriter_Expecter{mock: &_m.Mock} +} + +// Close provides a mock function with given fields: +func (_m *ContractWriter) Close() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Close") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ContractWriter_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' +type ContractWriter_Close_Call struct { + *mock.Call +} + +// Close is a helper method to define mock.On call +func (_e *ContractWriter_Expecter) Close() *ContractWriter_Close_Call { + return &ContractWriter_Close_Call{Call: _e.mock.On("Close")} +} + +func (_c *ContractWriter_Close_Call) Run(run func()) *ContractWriter_Close_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ContractWriter_Close_Call) Return(_a0 error) *ContractWriter_Close_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractWriter_Close_Call) RunAndReturn(run func() error) *ContractWriter_Close_Call { + _c.Call.Return(run) + return _c +} + +// GetFeeComponents provides a mock function with given fields: ctx +func (_m *ContractWriter) GetFeeComponents(ctx context.Context) (*types.ChainFeeComponents, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetFeeComponents") + } + + var r0 *types.ChainFeeComponents + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*types.ChainFeeComponents, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *types.ChainFeeComponents); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ChainFeeComponents) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractWriter_GetFeeComponents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeeComponents' +type ContractWriter_GetFeeComponents_Call struct { + *mock.Call +} + +// GetFeeComponents is a helper method to define mock.On call +// - ctx context.Context +func (_e *ContractWriter_Expecter) GetFeeComponents(ctx interface{}) *ContractWriter_GetFeeComponents_Call { + return &ContractWriter_GetFeeComponents_Call{Call: _e.mock.On("GetFeeComponents", ctx)} +} + +func (_c *ContractWriter_GetFeeComponents_Call) Run(run func(ctx context.Context)) *ContractWriter_GetFeeComponents_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *ContractWriter_GetFeeComponents_Call) Return(_a0 *types.ChainFeeComponents, _a1 error) *ContractWriter_GetFeeComponents_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractWriter_GetFeeComponents_Call) RunAndReturn(run func(context.Context) (*types.ChainFeeComponents, error)) *ContractWriter_GetFeeComponents_Call { + _c.Call.Return(run) + return _c +} + +// GetTransactionStatus provides a mock function with given fields: ctx, transactionID +func (_m *ContractWriter) GetTransactionStatus(ctx context.Context, transactionID string) (types.TransactionStatus, error) { + ret := _m.Called(ctx, transactionID) + + if len(ret) == 0 { + panic("no return value specified for GetTransactionStatus") + } + + var r0 types.TransactionStatus + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (types.TransactionStatus, error)); ok { + return rf(ctx, transactionID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) types.TransactionStatus); ok { + r0 = rf(ctx, transactionID) + } else { + r0 = ret.Get(0).(types.TransactionStatus) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, transactionID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractWriter_GetTransactionStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTransactionStatus' +type ContractWriter_GetTransactionStatus_Call struct { + *mock.Call +} + +// GetTransactionStatus is a helper method to define mock.On call +// - ctx context.Context +// - transactionID string +func (_e *ContractWriter_Expecter) GetTransactionStatus(ctx interface{}, transactionID interface{}) *ContractWriter_GetTransactionStatus_Call { + return &ContractWriter_GetTransactionStatus_Call{Call: _e.mock.On("GetTransactionStatus", ctx, transactionID)} +} + +func (_c *ContractWriter_GetTransactionStatus_Call) Run(run func(ctx context.Context, transactionID string)) *ContractWriter_GetTransactionStatus_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *ContractWriter_GetTransactionStatus_Call) Return(_a0 types.TransactionStatus, _a1 error) *ContractWriter_GetTransactionStatus_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractWriter_GetTransactionStatus_Call) RunAndReturn(run func(context.Context, string) (types.TransactionStatus, error)) *ContractWriter_GetTransactionStatus_Call { + _c.Call.Return(run) + return _c +} + +// HealthReport provides a mock function with given fields: +func (_m *ContractWriter) HealthReport() map[string]error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for HealthReport") + } + + var r0 map[string]error + if rf, ok := ret.Get(0).(func() map[string]error); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]error) + } + } + + return r0 +} + +// ContractWriter_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' +type ContractWriter_HealthReport_Call struct { + *mock.Call +} + +// HealthReport is a helper method to define mock.On call +func (_e *ContractWriter_Expecter) HealthReport() *ContractWriter_HealthReport_Call { + return &ContractWriter_HealthReport_Call{Call: _e.mock.On("HealthReport")} +} + +func (_c *ContractWriter_HealthReport_Call) Run(run func()) *ContractWriter_HealthReport_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ContractWriter_HealthReport_Call) Return(_a0 map[string]error) *ContractWriter_HealthReport_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractWriter_HealthReport_Call) RunAndReturn(run func() map[string]error) *ContractWriter_HealthReport_Call { + _c.Call.Return(run) + return _c +} + +// Name provides a mock function with given fields: +func (_m *ContractWriter) Name() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Name") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// ContractWriter_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' +type ContractWriter_Name_Call struct { + *mock.Call +} + +// Name is a helper method to define mock.On call +func (_e *ContractWriter_Expecter) Name() *ContractWriter_Name_Call { + return &ContractWriter_Name_Call{Call: _e.mock.On("Name")} +} + +func (_c *ContractWriter_Name_Call) Run(run func()) *ContractWriter_Name_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ContractWriter_Name_Call) Return(_a0 string) *ContractWriter_Name_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractWriter_Name_Call) RunAndReturn(run func() string) *ContractWriter_Name_Call { + _c.Call.Return(run) + return _c +} + +// Ready provides a mock function with given fields: +func (_m *ContractWriter) Ready() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Ready") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ContractWriter_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' +type ContractWriter_Ready_Call struct { + *mock.Call +} + +// Ready is a helper method to define mock.On call +func (_e *ContractWriter_Expecter) Ready() *ContractWriter_Ready_Call { + return &ContractWriter_Ready_Call{Call: _e.mock.On("Ready")} +} + +func (_c *ContractWriter_Ready_Call) Run(run func()) *ContractWriter_Ready_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ContractWriter_Ready_Call) Return(_a0 error) *ContractWriter_Ready_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractWriter_Ready_Call) RunAndReturn(run func() error) *ContractWriter_Ready_Call { + _c.Call.Return(run) + return _c +} + +// Start provides a mock function with given fields: _a0 +func (_m *ContractWriter) Start(_a0 context.Context) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Start") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ContractWriter_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type ContractWriter_Start_Call struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +// - _a0 context.Context +func (_e *ContractWriter_Expecter) Start(_a0 interface{}) *ContractWriter_Start_Call { + return &ContractWriter_Start_Call{Call: _e.mock.On("Start", _a0)} +} + +func (_c *ContractWriter_Start_Call) Run(run func(_a0 context.Context)) *ContractWriter_Start_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *ContractWriter_Start_Call) Return(_a0 error) *ContractWriter_Start_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractWriter_Start_Call) RunAndReturn(run func(context.Context) error) *ContractWriter_Start_Call { + _c.Call.Return(run) + return _c +} + +// SubmitTransaction provides a mock function with given fields: ctx, contractName, method, args, transactionID, toAddress, meta, value +func (_m *ContractWriter) SubmitTransaction(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int) error { + ret := _m.Called(ctx, contractName, method, args, transactionID, toAddress, meta, value) + + if len(ret) == 0 { + panic("no return value specified for SubmitTransaction") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error); ok { + r0 = rf(ctx, contractName, method, args, transactionID, toAddress, meta, value) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ContractWriter_SubmitTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubmitTransaction' +type ContractWriter_SubmitTransaction_Call struct { + *mock.Call +} + +// SubmitTransaction is a helper method to define mock.On call +// - ctx context.Context +// - contractName string +// - method string +// - args any +// - transactionID string +// - toAddress string +// - meta *types.TxMeta +// - value *big.Int +func (_e *ContractWriter_Expecter) SubmitTransaction(ctx interface{}, contractName interface{}, method interface{}, args interface{}, transactionID interface{}, toAddress interface{}, meta interface{}, value interface{}) *ContractWriter_SubmitTransaction_Call { + return &ContractWriter_SubmitTransaction_Call{Call: _e.mock.On("SubmitTransaction", ctx, contractName, method, args, transactionID, toAddress, meta, value)} +} + +func (_c *ContractWriter_SubmitTransaction_Call) Run(run func(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int)) *ContractWriter_SubmitTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(any), args[4].(string), args[5].(string), args[6].(*types.TxMeta), args[7].(*big.Int)) + }) + return _c +} + +func (_c *ContractWriter_SubmitTransaction_Call) Return(_a0 error) *ContractWriter_SubmitTransaction_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractWriter_SubmitTransaction_Call) RunAndReturn(run func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error) *ContractWriter_SubmitTransaction_Call { + _c.Call.Return(run) + return _c +} + +// NewContractWriter creates a new instance of ContractWriter. 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 NewContractWriter(t interface { + mock.TestingT + Cleanup(func()) +}) *ContractWriter { + mock := &ContractWriter{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go index 8fe0d58018a..09a0bbd2b36 100644 --- a/core/capabilities/targets/write_target.go +++ b/core/capabilities/targets/write_target.go @@ -31,7 +31,7 @@ const transactionStatusCheckInterval = 2 * time.Second type WriteTarget struct { cr ContractValueGetter - cw commontypes.ChainWriter + cw commontypes.ContractWriter binding commontypes.BoundContract forwarderAddress string // The minimum amount of gas that the receiver contract must get to process the forwarder report @@ -67,7 +67,7 @@ func NewWriteTarget( lggr logger.Logger, id string, cr ContractValueGetter, - cw commontypes.ChainWriter, + cw commontypes.ContractWriter, forwarderAddress string, txGasLimit uint64, ) *WriteTarget { diff --git a/core/capabilities/targets/write_target_test.go b/core/capabilities/targets/write_target_test.go index 801bdf2ea9a..a702d78cb5d 100644 --- a/core/capabilities/targets/write_target_test.go +++ b/core/capabilities/targets/write_target_test.go @@ -27,7 +27,7 @@ func TestWriteTarget(t *testing.T) { lggr := logger.TestLogger(t) ctx := context.Background() - cw := mocks.NewChainWriter(t) + cw := mocks.NewContractWriter(t) cr := mocks.NewContractValueGetter(t) forwarderA := testutils.NewAddress() diff --git a/core/capabilities/webapi/outgoing_connector_handler.go b/core/capabilities/webapi/outgoing_connector_handler.go index b00b82b2bd0..d18ee971d1a 100644 --- a/core/capabilities/webapi/outgoing_connector_handler.go +++ b/core/capabilities/webapi/outgoing_connector_handler.go @@ -10,6 +10,7 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" @@ -19,6 +20,7 @@ import ( var _ connector.GatewayConnectorHandler = &OutgoingConnectorHandler{} type OutgoingConnectorHandler struct { + services.StateMachine gc connector.GatewayConnector method string lggr logger.Logger @@ -98,7 +100,7 @@ func (c *OutgoingConnectorHandler) HandleGatewayMessage(ctx context.Context, gat } l.Debugw("handling gateway request") switch body.Method { - case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction: + case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction, capabilities.MethodWorkflowSyncer: body := &msg.Body var payload capabilities.Response err := json.Unmarshal(body.Payload, &payload) @@ -125,16 +127,28 @@ func (c *OutgoingConnectorHandler) HandleGatewayMessage(ctx context.Context, gat } func (c *OutgoingConnectorHandler) Start(ctx context.Context) error { - return c.gc.AddHandler([]string{c.method}, c) + return c.StartOnce("OutgoingConnectorHandler", func() error { + return c.gc.AddHandler([]string{c.method}, c) + }) } func (c *OutgoingConnectorHandler) Close() error { - return nil + return c.StopOnce("OutgoingConnectorHandler", func() error { + return nil + }) +} + +func (c *OutgoingConnectorHandler) HealthReport() map[string]error { + return map[string]error{c.Name(): c.Healthy()} +} + +func (c *OutgoingConnectorHandler) Name() string { + return c.lggr.Name() } func validMethod(method string) bool { switch method { - case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction: + case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction, capabilities.MethodWorkflowSyncer: return true default: return false diff --git a/core/capabilities/webapi/target/target.go b/core/capabilities/webapi/target/target.go index 4576f95a54e..b211e0fe837 100644 --- a/core/capabilities/webapi/target/target.go +++ b/core/capabilities/webapi/target/target.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "strings" + "time" "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -57,6 +58,12 @@ func (c *Capability) Start(ctx context.Context) error { } func (c *Capability) Close() error { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + err := c.registry.Remove(ctx, c.capabilityInfo.ID) + if err != nil { + return err + } return nil } diff --git a/core/capabilities/webapi/trigger/trigger.go b/core/capabilities/webapi/trigger/trigger.go index c607f0dbb6f..712cf38a4cc 100644 --- a/core/capabilities/webapi/trigger/trigger.go +++ b/core/capabilities/webapi/trigger/trigger.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "sync" + "time" ethCommon "github.com/ethereum/go-ethereum/common" @@ -256,6 +257,12 @@ func (h *triggerConnectorHandler) Start(ctx context.Context) error { } func (h *triggerConnectorHandler) Close() error { return h.StopOnce("GatewayConnectorServiceWrapper", func() error { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + err := h.registry.Remove(ctx, h.ID) + if err != nil { + return err + } return nil }) } diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go index c44cebe0840..a67670df318 100644 --- a/core/chains/evm/client/simulated_backend_client.go +++ b/core/chains/evm/client/simulated_backend_client.go @@ -5,6 +5,7 @@ import ( "context" "errors" "fmt" + "math" "math/big" "strings" "testing" @@ -357,9 +358,12 @@ func (c *SimulatedBackendClient) SubscribeToHeads( case h := <-ch: var head *evmtypes.Head if h != nil { + if h.Time > math.MaxInt64 { + c.t.Fatalf("time overflows int64: %d", h.Time) + } head = &evmtypes.Head{ Difficulty: h.Difficulty, - Timestamp: time.Unix(int64(h.Time), 0), //nolint:gosec + Timestamp: time.Unix(int64(h.Time), 0), //nolint:gosec // G115 false positive Number: h.Number.Int64(), Hash: h.Hash(), ParentHash: h.ParentHash, diff --git a/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml b/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml index 85282ea81b3..c4e0cef4c61 100644 --- a/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml @@ -16,3 +16,6 @@ OracleType = 'zksync' [HeadTracker] HistoryDepth = 50 + +[OCR2.Automation] +GasLimit = 6_000_000 diff --git a/core/chains/evm/config/toml/defaults/zkSync_Sepolia.toml b/core/chains/evm/config/toml/defaults/zkSync_Sepolia.toml index 78ed3c0768d..ed7c37b8ca1 100644 --- a/core/chains/evm/config/toml/defaults/zkSync_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/zkSync_Sepolia.toml @@ -16,3 +16,6 @@ OracleType = 'zksync' [HeadTracker] HistoryDepth = 50 + +[OCR2.Automation] +GasLimit = 6_000_000 diff --git a/core/chains/evm/label/label.go b/core/chains/evm/label/label.go index 4cca89f93fb..b6e80acfadf 100644 --- a/core/chains/evm/label/label.go +++ b/core/chains/evm/label/label.go @@ -1,6 +1,5 @@ package label -// nolint const ( MaxInFlightTransactionsWarning = `WARNING: If this happens a lot, you may need to increase EVM.Transactions.MaxInFlight to boost your node's transaction throughput, however you do this at your own risk. You MUST first ensure your ethereum node is configured not to ever evict local transactions that exceed this number otherwise the node can get permanently stuck. See the performance guide for more details: https://docs.chain.link/docs/evm-performance-configuration/` MaxQueuedTransactionsWarning = `WARNING: Hitting EVM.Transactions.MaxQueued is a sanity limit and should never happen under normal operation. Unless you are operating with very high throughput, this error is unlikely to be a problem with your Chainlink node configuration, and instead more likely to be caused by a problem with your eth node's connectivity. Check your eth node: it may not be broadcasting transactions to the network, or it might be overloaded and evicting Chainlink's transactions from its mempool. It is recommended to run Chainlink with multiple primary and sendonly nodes for redundancy and to ensure fast and reliable transaction propagation. Increasing EVM.Transactions.MaxQueued will allow Chainlink to buffer more unsent transactions, but you should only do this if you need very high burst transmission rates. If you don't need very high burst throughput, increasing this limit is not the correct action to take here and will probably make things worse. See the performance guide for more details: https://docs.chain.link/docs/evm-performance-configuration/` diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index 3848c44da82..6ef4fefecee 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -8,7 +8,7 @@ import ( "errors" "fmt" "math/big" - "math/rand" + "math/rand/v2" "sort" "strings" "sync" @@ -687,7 +687,7 @@ func (lp *logPoller) backgroundWorkerRun() { // Start initial prune of unmatched logs after 5-15 successful expired log prunes, so that not all chains start // around the same time. After that, every 20 successful expired log prunes. - successfulExpiredLogPrunes := 5 + rand.Intn(10) //nolint:gosec + successfulExpiredLogPrunes := 5 + rand.IntN(10) //nolint:gosec // G404 for { select { diff --git a/core/chains/evm/txmgr/client.go b/core/chains/evm/txmgr/client.go index 9b2bcab6ebc..9ec175048d3 100644 --- a/core/chains/evm/txmgr/client.go +++ b/core/chains/evm/txmgr/client.go @@ -121,7 +121,7 @@ func (c *evmTxmClient) SequenceAt(ctx context.Context, addr common.Address, bloc if nonce > math.MaxInt64 { return 0, fmt.Errorf("overflow for nonce: %d", nonce) } - //nolint:gosec // disable G115 + return evmtypes.Nonce(nonce), err } diff --git a/core/cmd/shell.go b/core/cmd/shell.go index 1edd53c1efc..53ba5e3f82f 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -37,6 +37,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -52,6 +53,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/cache" "github.com/smartcontractkit/chainlink/v2/core/services/versioning" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows" "github.com/smartcontractkit/chainlink/v2/core/sessions" "github.com/smartcontractkit/chainlink/v2/core/static" "github.com/smartcontractkit/chainlink/v2/core/store/migrate" @@ -110,6 +112,10 @@ func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing, cfgTeleme AuthPublicKeyHex: csaPubKeyHex, AuthHeaders: beholderAuthHeaders, } + // note: due to the OTEL specification, all histogram buckets + // must be defined when the beholder client is created + clientCfg.MetricViews = append(clientCfg.MetricViews, workflows.MetricViews()...) + if tracingCfg.Enabled { clientCfg.TraceSpanExporter, err = tracingCfg.NewSpanExporter() if err != nil { @@ -269,6 +275,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G solanaCfg := chainlink.SolanaFactoryConfig{ Keystore: keyStore.Solana(), TOMLConfigs: cfg.SolanaConfigs(), + DS: ds, } initOps = append(initOps, chainlink.InitSolana(ctx, relayerFactory, solanaCfg)) } diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index bead4ba5afd..412231308b6 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -469,14 +469,12 @@ func (s *Shell) runNode(c *cli.Context) error { } } - if s.Config.Capabilities().WorkflowRegistry().Address() != "" { - err2 := app.GetKeyStore().Workflow().EnsureKey(rootCtx) - if err2 != nil { - return errors.Wrap(err2, "failed to ensure workflow key") - } + err2 := app.GetKeyStore().Workflow().EnsureKey(rootCtx) + if err2 != nil { + return errors.Wrap(err2, "failed to ensure workflow key") } - err2 := app.GetKeyStore().CSA().EnsureKey(rootCtx) + err2 = app.GetKeyStore().CSA().EnsureKey(rootCtx) if err2 != nil { return errors.Wrap(err2, "failed to ensure CSA key") } @@ -686,7 +684,6 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) { nonces[i] = evmtypes.Nonce(beginningNonce + i) } if gasPriceWei <= math.MaxInt64 { - //nolint:gosec // disable G115 return s.errorOut(ec.ForceRebroadcast(ctx, nonces, gas.EvmFee{GasPrice: assets.NewWeiI(int64(gasPriceWei))}, address, uint64(overrideGasLimit))) } return s.errorOut(fmt.Errorf("integer overflow conversion error. GasPrice: %v", gasPriceWei)) diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index 13b914ba1c7..e73e1d51f24 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -18,8 +18,10 @@ import ( "github.com/urfave/cli" commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/sqltest" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" + "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -353,6 +355,7 @@ func TestSetupSolanaRelayer(t *testing.T) { lggr := logger.TestLogger(t) reg := plugins.NewLoopRegistry(lggr, nil, nil, nil, "") ks := mocks.NewSolana(t) + ds := sqltest.NewNoOpDataSource() // config 3 chains but only enable 2 => should only be 2 relayer nEnabledChains := 2 @@ -395,9 +398,14 @@ func TestSetupSolanaRelayer(t *testing.T) { LoopRegistry: reg, } + cfg := chainlink.SolanaFactoryConfig{ + Keystore: ks, + TOMLConfigs: tConfig.SolanaConfigs(), + DS: ds} + // not parallel; shared state t.Run("no plugin", func(t *testing.T) { - relayers, err := rf.NewSolana(ks, tConfig.SolanaConfigs()) + relayers, err := rf.NewSolana(cfg) require.NoError(t, err) require.NotNil(t, relayers) require.Len(t, relayers, nEnabledChains) @@ -408,7 +416,7 @@ func TestSetupSolanaRelayer(t *testing.T) { t.Run("plugin", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") - relayers, err := rf.NewSolana(ks, tConfig.SolanaConfigs()) + relayers, err := rf.NewSolana(cfg) require.NoError(t, err) require.NotNil(t, relayers) require.Len(t, relayers, nEnabledChains) @@ -433,16 +441,21 @@ func TestSetupSolanaRelayer(t *testing.T) { }, } }) + dupCfg := chainlink.SolanaFactoryConfig{ + Keystore: ks, + TOMLConfigs: duplicateConfig.SolanaConfigs(), + DS: ds, + } // not parallel; shared state t.Run("no plugin, duplicate chains", func(t *testing.T) { - _, err := rf.NewSolana(ks, duplicateConfig.SolanaConfigs()) + _, err := rf.NewSolana(dupCfg) require.Error(t, err) }) t.Run("plugin, duplicate chains", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") - _, err := rf.NewSolana(ks, duplicateConfig.SolanaConfigs()) + _, err := rf.NewSolana(dupCfg) require.Error(t, err) }) @@ -450,7 +463,11 @@ func TestSetupSolanaRelayer(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") t.Setenv("CL_SOLANA_ENV", "fake_path") - _, err := rf.NewSolana(ks, t2Config.SolanaConfigs()) + _, err := rf.NewSolana(chainlink.SolanaFactoryConfig{ + Keystore: ks, + TOMLConfigs: t2Config.SolanaConfigs(), + DS: ds, + }) require.Error(t, err) require.Contains(t, err.Error(), "failed to parse Solana env file") }) @@ -458,7 +475,7 @@ func TestSetupSolanaRelayer(t *testing.T) { t.Run("plugin already registered", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") - _, err := rf.NewSolana(ks, tConfig.SolanaConfigs()) + _, err := rf.NewSolana(cfg) require.Error(t, err) require.Contains(t, err.Error(), "failed to create Solana LOOP command") }) diff --git a/core/config/app_config.go b/core/config/app_config.go index 4cb7f1f610c..3f2a5472b24 100644 --- a/core/config/app_config.go +++ b/core/config/app_config.go @@ -8,7 +8,6 @@ import ( "go.uber.org/zap/zapcore" ) -// nolint var ( ErrEnvUnset = pkgerrors.New("env var unset") ) diff --git a/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go index 78f051a4b9b..def5c4bc258 100644 --- a/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go @@ -81,8 +81,8 @@ type TokenPoolChainUpdate struct { } var BurnFromMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b5060405162004a6a38038062004a6a833981016040819052620000359162000869565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000165565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0385811660805282811660c05260ff851660a052600480546001600160a01b031916918316919091179055825115801560e0526200013b576040805160008152602081019091526200013b9084620001df565b506200015a935050506001600160a01b0387169050306000196200033c565b505050505062000ac0565b336001600160a01b038216036200018f57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e05162000200576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200028b57600083828151811062000224576200022462000994565b602090810291909101015190506200023e60028262000422565b1562000281576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000203565b5060005b815181101562000337576000828281518110620002b057620002b062000994565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002dc57506200032e565b620002e960028262000442565b156200032c576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b6001016200028f565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200038e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003b49190620009aa565b620003c09190620009da565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200041c918691906200045916565b50505050565b600062000439836001600160a01b0384166200052e565b90505b92915050565b600062000439836001600160a01b03841662000632565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490820152600090620004a8906001600160a01b03851690849062000684565b805190915015620003375780806020019051810190620004c99190620009f0565b620003375760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084015b60405180910390fd5b60008181526001830160205260408120548015620006275760006200055560018362000a1b565b85549091506000906200056b9060019062000a1b565b9050808214620005d75760008660000182815481106200058f576200058f62000994565b9060005260206000200154905080876000018481548110620005b557620005b562000994565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620005eb57620005eb62000a31565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200043c565b60009150506200043c565b60008181526001830160205260408120546200067b575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200043c565b5060006200043c565b60606200069584846000856200069d565b949350505050565b606082471015620007005760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000525565b600080866001600160a01b031685876040516200071e919062000a6d565b60006040518083038185875af1925050503d80600081146200075d576040519150601f19603f3d011682016040523d82523d6000602084013e62000762565b606091505b509092509050620007768783838762000781565b979650505050505050565b60608315620007f5578251600003620007ed576001600160a01b0385163b620007ed5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000525565b508162000695565b6200069583838151156200080c5781518083602001fd5b8060405162461bcd60e51b815260040162000525919062000a8b565b6001600160a01b03811681146200083e57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620008648162000828565b919050565b600080600080600060a086880312156200088257600080fd5b85516200088f8162000828565b8095505060208087015160ff81168114620008a957600080fd5b60408801519095506001600160401b0380821115620008c757600080fd5b818901915089601f830112620008dc57600080fd5b815181811115620008f157620008f162000841565b8060051b604051601f19603f8301168101818110858211171562000919576200091962000841565b60405291825284820192508381018501918c8311156200093857600080fd5b938501935b828510156200096157620009518562000857565b845293850193928501926200093d565b809850505050505050620009786060870162000857565b9150620009886080870162000857565b90509295509295909350565b634e487b7160e01b600052603260045260246000fd5b600060208284031215620009bd57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156200043c576200043c620009c4565b60006020828403121562000a0357600080fd5b8151801515811462000a1457600080fd5b9392505050565b818103818111156200043c576200043c620009c4565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000a6457818101518382015260200162000a4a565b50506000910152565b6000825162000a8181846020870162000a47565b9190910192915050565b602081526000825180602084015262000aac81604085016020870162000a47565b601f01601f19169190910160400192915050565b60805160a05160c05160e051613f0762000b636000396000818161054f01528181611c5b01526126ac0152600081816105290152818161189f0152611f470152600081816102e001528181610ba901528181611a4801528181611b0201528181611b3601528181611b670152611bae0152600081816102470152818161029c01528181610708015281816120ca0152818161264201526128970152613f076000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610527578063e0351e131461054d578063e8a1da1714610573578063f2fde38b1461058657600080fd5b8063c0d78655146104d9578063c4bffe2b146104ec578063c75eea9c14610501578063cf7401f31461051457600080fd5b8063acfecf91116100de578063acfecf9114610426578063af58d59f14610439578063b0f479a1146104a8578063b7946580146104c657600080fd5b80639a4575b9146103d1578063a42a7b8b146103f1578063a7cd63b71461041157600080fd5b806354c8a4f31161017157806379ba50971161014b57806379ba5097146103855780637d54534e1461038d5780638926f54f146103a05780638da5cb5b146103b357600080fd5b806354c8a4f31461033f57806362ddd3c4146103545780636d3d1a581461036757600080fd5b8063240028e8116101ad578063240028e81461028c57806324f65ee7146102d9578063390775371461030a5780634c5ef0ed1461032c57600080fd5b806301ffc9a7146101d4578063181f5a77146101fc57806321df0da714610245575b600080fd5b6101e76101e2366004613057565b610599565b60405190151581526020015b60405180910390f35b6102386040518060400160405280601b81526020017f4275726e46726f6d4d696e74546f6b656e506f6f6c20312e352e31000000000081525081565b6040516101f391906130fd565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b6101e761029a366004613132565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101f3565b61031d61031836600461314f565b61067e565b604051905181526020016101f3565b6101e761033a3660046131a8565b61084d565b61035261034d366004613277565b610897565b005b6103526103623660046131a8565b610912565b60095473ffffffffffffffffffffffffffffffffffffffff16610267565b6103526109af565b61035261039b366004613132565b610a7d565b6101e76103ae3660046132e3565b610afe565b60015473ffffffffffffffffffffffffffffffffffffffff16610267565b6103e46103df3660046132fe565b610b15565b6040516101f39190613339565b6104046103ff3660046132e3565b610bee565b6040516101f39190613390565b610419610d59565b6040516101f39190613412565b6103526104343660046131a8565b610d6a565b61044c6104473660046132e3565b610e82565b6040516101f3919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610267565b6102386104d43660046132e3565b610f57565b6103526104e7366004613132565b611007565b6104f46110e2565b6040516101f3919061346c565b61044c61050f3660046132e3565b61119a565b6103526105223660046135f4565b61126c565b7f0000000000000000000000000000000000000000000000000000000000000000610267565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b610352610581366004613277565b6112f0565b610352610594366004613132565b611802565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067857507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60408051602081019091526000815261069682611816565b60006106ef60608401356106ea6106b060c0870187613639565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3a92505050565b611afe565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961073d6060860160408701613132565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107aa57600080fd5b505af11580156107be573d6000803e3d6000fd5b506107d3925050506060840160408501613132565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161083191815260200190565b60405180910390a3604080516020810190915290815292915050565b600061088f838360405161086292919061369e565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611bee565b949350505050565b61089f611c06565b61090c84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611c5992505050565b50505050565b61091a611c06565b61092383610afe565b61096a576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109aa8383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e0f92505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a00576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a85611c06565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610678600567ffffffffffffffff8416611bee565b6040805180820190915260608082526020820152610b3282611f09565b610b3f8260600135612095565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b998460200160208101906104d491906132e3565b8152602001610be66040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610c1790600501612137565b90506000815167ffffffffffffffff811115610c3557610c356134ae565b604051908082528060200260200182016040528015610c6857816020015b6060815260200190600190039081610c535790505b50905060005b8251811015610d515760086000848381518110610c8d57610c8d6136ae565b602002602001015181526020019081526020016000208054610cae906136dd565b80601f0160208091040260200160405190810160405280929190818152602001828054610cda906136dd565b8015610d275780601f10610cfc57610100808354040283529160200191610d27565b820191906000526020600020905b815481529060010190602001808311610d0a57829003601f168201915b5050505050828281518110610d3e57610d3e6136ae565b6020908102919091010152600101610c6e565b509392505050565b6060610d656002612137565b905090565b610d72611c06565b610d7b83610afe565b610dbd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b610dfd8282604051610dd092919061369e565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190612144565b610e39578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161096193929190613779565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610e7592919061379d565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261067890612150565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610f82906136dd565b80601f0160208091040260200160405190810160405280929190818152602001828054610fae906136dd565b8015610ffb5780601f10610fd057610100808354040283529160200191610ffb565b820191906000526020600020905b815481529060010190602001808311610fde57829003601f168201915b50505050509050919050565b61100f611c06565b73ffffffffffffffffffffffffffffffffffffffff811661105c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110f06005612137565b90506000815167ffffffffffffffff81111561110e5761110e6134ae565b604051908082528060200260200182016040528015611137578160200160208202803683370190505b50905060005b825181101561119357828181518110611158576111586136ae565b6020026020010151828281518110611172576111726136ae565b67ffffffffffffffff9092166020928302919091019091015260010161113d565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261067890612150565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906112ac575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112e5576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b6109aa838383612202565b6112f8611c06565b60005b838110156114e5576000858583818110611317576113176136ae565b905060200201602081019061132c91906132e3565b9050611343600567ffffffffffffffff8316612144565b611385576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b67ffffffffffffffff811660009081526007602052604081206113aa90600501612137565b905060005b81518110156114165761140d8282815181106113cd576113cd6136ae565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161214490919063ffffffff16565b506001016113af565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff0000000000000000000000000000000000000000009081168255600182018390556002820180549091169055600381018290559061147f6004830182612fea565b60058201600081816114918282613024565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506114d3915050565b60405180910390a150506001016112fb565b5060005b818110156117fb576000838383818110611505576115056136ae565b905060200281019061151791906137b1565b6115209061387d565b9050611531816060015160006122ec565b611540816080015160006122ec565b80604001515160000361157f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516115979060059067ffffffffffffffff16612429565b6115dc5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610961565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a90910299909316171790941695909517909255909202909117600382015590820151600482019061175f90826139f4565b5060005b8260200151518110156117a35761179b83600001518460200151838151811061178e5761178e6136ae565b6020026020010151611e0f565b600101611763565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516117e99493929190613b0e565b60405180910390a150506001016114e9565b5050505050565b61180a611c06565b61181381612435565b50565b61182961029a60a0830160808401613132565b6118885761183d60a0820160808301613132565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610961565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6118d460408401602085016132e3565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119699190613ba7565b156119a0576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b86119b360408301602084016132e3565b6124f9565b6119d86119cb60408301602084016132e3565b61033a60a0840184613639565b611a1d576119e960a0820182613639565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161096192919061379d565b611813611a3060408301602084016132e3565b826060013561261f565b60008151600003611a6c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611aa957816040517f953576f700000000000000000000000000000000000000000000000000000000815260040161096191906130fd565b600082806020019051810190611abf9190613bc4565b905060ff81111561067857826040517f953576f700000000000000000000000000000000000000000000000000000000815260040161096191906130fd565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611b34575081610678565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611ba857611b8c7f000000000000000000000000000000000000000000000000000000000000000083613c0c565b611b9790600a613d45565b611ba19084613d54565b9050610678565b611bd2827f0000000000000000000000000000000000000000000000000000000000000000613c0c565b611bdd90600a613d45565b611be79084613d8f565b9392505050565b60008181526001830160205260408120541515611be7565b60015473ffffffffffffffffffffffffffffffffffffffff163314611c57576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611cb0576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611d46576000838281518110611cd057611cd06136ae565b60200260200101519050611cee81600261266690919063ffffffff16565b15611d3d5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611cb3565b5060005b81518110156109aa576000828281518110611d6757611d676136ae565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611dab5750611e07565b611db6600282612688565b15611e055760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611d4a565b8051600003611e4a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611e7c9060050182612429565b611eb65782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610961929190613da6565b6000818152600860205260409020611ece83826139f4565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610e7591906130fd565b611f1c61029a60a0830160808401613132565b611f305761183d60a0820160808301613132565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611f7c60408401602085016132e3565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611fed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120119190613ba7565b15612048576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61206061205b6060830160408401613132565b6126aa565b61207861207360408301602084016132e3565b612729565b61181361208b60408301602084016132e3565b8260600135612877565b6040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906379cc679090604401600060405180830381600087803b15801561212357600080fd5b505af11580156117fb573d6000803e3d6000fd5b60606000611be7836128bb565b6000611be78383612916565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526121de82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426121c29190613dc9565b85608001516fffffffffffffffffffffffffffffffff16612a09565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61220b83610afe565b61224d576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b6122588260006122ec565b67ffffffffffffffff8316600090815260076020526040902061227b9083612a31565b6122868160006122ec565b67ffffffffffffffff831660009081526007602052604090206122ac9060020182612a31565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516122df93929190613ddc565b60405180910390a1505050565b8151156123b75781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612342575060408201516fffffffffffffffffffffffffffffffff16155b1561237b57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016109619190613e5f565b80156123b3576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff161515806123f0575060208201516fffffffffffffffffffffffffffffffff1615155b156123b357816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016109619190613e5f565b6000611be78383612bd3565b3373ffffffffffffffffffffffffffffffffffffffff821603612484576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61250281610afe565b612544576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156125c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e79190613ba7565b611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206123b390600201827f0000000000000000000000000000000000000000000000000000000000000000612c22565b6000611be78373ffffffffffffffffffffffffffffffffffffffff8416612916565b6000611be78373ffffffffffffffffffffffffffffffffffffffff8416612bd3565b7f000000000000000000000000000000000000000000000000000000000000000015611813576126db600282612fa5565b611813576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610961565b61273281610afe565b612774576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa1580156127ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128119190613e9b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206123b390827f0000000000000000000000000000000000000000000000000000000000000000612c22565b606081600001805480602002602001604051908101604052809291908181526020018280548015610ffb57602002820191906000526020600020905b8154815260200190600101908083116128f75750505050509050919050565b600081815260018301602052604081205480156129ff57600061293a600183613dc9565b855490915060009061294e90600190613dc9565b90508082146129b357600086600001828154811061296e5761296e6136ae565b9060005260206000200154905080876000018481548110612991576129916136ae565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806129c4576129c4613eb8565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610678565b6000915050610678565b6000612a2885612a198486613d8f565b612a239087613ee7565b612fd4565b95945050505050565b8154600090612a5a90700100000000000000000000000000000000900463ffffffff1642613dc9565b90508015612afc5760018301548354612aa2916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612a09565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612b22916fffffffffffffffffffffffffffffffff9081169116612fd4565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906122df908490613e5f565b6000818152600183016020526040812054612c1a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610678565b506000610678565b825474010000000000000000000000000000000000000000900460ff161580612c49575081155b15612c5357505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612c9990700100000000000000000000000000000000900463ffffffff1642613dc9565b90508015612d595781831115612cdb576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612d159083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612a09565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612e105773ffffffffffffffffffffffffffffffffffffffff8416612db8576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610961565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610961565b84831015612f235760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612e549082613dc9565b612e5e878a613dc9565b612e689190613ee7565b612e729190613d54565b905073ffffffffffffffffffffffffffffffffffffffff8616612ecb576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610961565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610961565b612f2d8584613dc9565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611be7565b6000818310612fe35781611be7565b5090919050565b508054612ff6906136dd565b6000825580601f10613006575050565b601f016020900490600052602060002090810190611813919061303e565b508054600082559060005260206000209081019061181391905b5b80821115613053576000815560010161303f565b5090565b60006020828403121561306957600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611be757600080fd5b6000815180845260005b818110156130bf576020818501810151868301820152016130a3565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611be76020830184613099565b73ffffffffffffffffffffffffffffffffffffffff8116811461181357600080fd5b60006020828403121561314457600080fd5b8135611be781613110565b60006020828403121561316157600080fd5b813567ffffffffffffffff81111561317857600080fd5b82016101008185031215611be757600080fd5b803567ffffffffffffffff811681146131a357600080fd5b919050565b6000806000604084860312156131bd57600080fd5b6131c68461318b565b9250602084013567ffffffffffffffff808211156131e357600080fd5b818601915086601f8301126131f757600080fd5b81358181111561320657600080fd5b87602082850101111561321857600080fd5b6020830194508093505050509250925092565b60008083601f84011261323d57600080fd5b50813567ffffffffffffffff81111561325557600080fd5b6020830191508360208260051b850101111561327057600080fd5b9250929050565b6000806000806040858703121561328d57600080fd5b843567ffffffffffffffff808211156132a557600080fd5b6132b18883890161322b565b909650945060208701359150808211156132ca57600080fd5b506132d78782880161322b565b95989497509550505050565b6000602082840312156132f557600080fd5b611be78261318b565b60006020828403121561331057600080fd5b813567ffffffffffffffff81111561332757600080fd5b820160a08185031215611be757600080fd5b6020815260008251604060208401526133556060840182613099565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612a288282613099565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613405577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526133f3858351613099565b945092850192908501906001016133b9565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561346057835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161342e565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561346057835167ffffffffffffffff1683529284019291840191600101613488565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613500576135006134ae565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561354d5761354d6134ae565b604052919050565b801515811461181357600080fd5b80356fffffffffffffffffffffffffffffffff811681146131a357600080fd5b60006060828403121561359557600080fd5b6040516060810181811067ffffffffffffffff821117156135b8576135b86134ae565b60405290508082356135c981613555565b81526135d760208401613563565b60208201526135e860408401613563565b60408201525092915050565b600080600060e0848603121561360957600080fd5b6136128461318b565b92506136218560208601613583565b91506136308560808601613583565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261366e57600080fd5b83018035915067ffffffffffffffff82111561368957600080fd5b60200191503681900382131561327057600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c908216806136f157607f821691505b60208210810361372a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612a28604083018486613730565b60208152600061088f602083018486613730565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181126137e557600080fd5b9190910192915050565b600082601f83011261380057600080fd5b813567ffffffffffffffff81111561381a5761381a6134ae565b61384b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613506565b81815284602083860101111561386057600080fd5b816020850160208301376000918101602001919091529392505050565b6000610120823603121561389057600080fd5b6138986134dd565b6138a18361318b565b815260208084013567ffffffffffffffff808211156138bf57600080fd5b9085019036601f8301126138d257600080fd5b8135818111156138e4576138e46134ae565b8060051b6138f3858201613506565b918252838101850191858101903684111561390d57600080fd5b86860192505b838310156139495782358581111561392b5760008081fd5b6139393689838a01016137ef565b8352509186019190860190613913565b808789015250505050604086013592508083111561396657600080fd5b5050613974368286016137ef565b6040830152506139873660608501613583565b60608201526139993660c08501613583565b608082015292915050565b601f8211156109aa576000816000526020600020601f850160051c810160208610156139cd5750805b601f850160051c820191505b818110156139ec578281556001016139d9565b505050505050565b815167ffffffffffffffff811115613a0e57613a0e6134ae565b613a2281613a1c84546136dd565b846139a4565b602080601f831160018114613a755760008415613a3f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556139ec565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613ac257888601518255948401946001909101908401613aa3565b5085821015613afe57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613b3281840187613099565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613b709050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612a28565b600060208284031215613bb957600080fd5b8151611be781613555565b600060208284031215613bd657600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561067857610678613bdd565b600181815b80851115613c7e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613c6457613c64613bdd565b80851615613c7157918102915b93841c9390800290613c2a565b509250929050565b600082613c9557506001610678565b81613ca257506000610678565b8160018114613cb85760028114613cc257613cde565b6001915050610678565b60ff841115613cd357613cd3613bdd565b50506001821b610678565b5060208310610133831016604e8410600b8410161715613d01575081810a610678565b613d0b8383613c25565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613d3d57613d3d613bdd565b029392505050565b6000611be760ff841683613c86565b600082613d8a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761067857610678613bdd565b67ffffffffffffffff8316815260406020820152600061088f6040830184613099565b8181038181111561067857610678613bdd565b67ffffffffffffffff8416815260e08101613e2860208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c083015261088f565b6060810161067882848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613ead57600080fd5b8151611be781613110565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561067857610678613bdd56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b5060405162004c6338038062004c63833981016040819052620000359162000918565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000206565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e9181019062000a3a565b60015b1562000192578060ff168560ff161462000190576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dc57604080516000815260208101909152620001dc908462000280565b50620001fb935050506001600160a01b038716905030600019620003dd565b505050505062000b84565b336001600160a01b038216036200023057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e051620002a1576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200032c576000838281518110620002c557620002c562000a58565b60209081029190910101519050620002df600282620004c3565b1562000322576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620002a4565b5060005b8151811015620003d857600082828151811062000351576200035162000a58565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200037d5750620003cf565b6200038a600282620004e3565b15620003cd576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000330565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200042f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000455919062000a6e565b62000461919062000a9e565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004bd91869190620004fa16565b50505050565b6000620004da836001600160a01b038416620005cb565b90505b92915050565b6000620004da836001600160a01b038416620006cf565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000549906001600160a01b03851690849062000721565b805190915015620003d857808060200190518101906200056a919062000ab4565b620003d85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000187565b60008181526001830160205260408120548015620006c4576000620005f260018362000adf565b8554909150600090620006089060019062000adf565b9050808214620006745760008660000182815481106200062c576200062c62000a58565b906000526020600020015490508087600001848154811062000652576200065262000a58565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000688576200068862000af5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004dd565b6000915050620004dd565b60008181526001830160205260408120546200071857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004dd565b506000620004dd565b60606200073284846000856200073a565b949350505050565b6060824710156200079d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000187565b600080866001600160a01b03168587604051620007bb919062000b31565b60006040518083038185875af1925050503d8060008114620007fa576040519150601f19603f3d011682016040523d82523d6000602084013e620007ff565b606091505b50909250905062000813878383876200081e565b979650505050505050565b60608315620008925782516000036200088a576001600160a01b0385163b6200088a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000187565b508162000732565b620007328383815115620008a95781518083602001fd5b8060405162461bcd60e51b815260040162000187919062000b4f565b6001600160a01b0381168114620008db57600080fd5b50565b805160ff81168114620008f057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620008f081620008c5565b600080600080600060a086880312156200093157600080fd5b85516200093e81620008c5565b945060206200094f878201620008de565b60408801519095506001600160401b03808211156200096d57600080fd5b818901915089601f8301126200098257600080fd5b815181811115620009975762000997620008f5565b8060051b604051601f19603f83011681018181108582111715620009bf57620009bf620008f5565b60405291825284820192508381018501918c831115620009de57600080fd5b938501935b8285101562000a0757620009f7856200090b565b84529385019392850192620009e3565b80985050505050505062000a1e606087016200090b565b915062000a2e608087016200090b565b90509295509295909350565b60006020828403121562000a4d57600080fd5b620004da82620008de565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a8157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620004dd57620004dd62000a88565b60006020828403121562000ac757600080fd5b8151801515811462000ad857600080fd5b9392505050565b81810381811115620004dd57620004dd62000a88565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000b2857818101518382015260200162000b0e565b50506000910152565b6000825162000b4581846020870162000b0b565b9190910192915050565b602081526000825180602084015262000b7081604085016020870162000b0b565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161402e62000c356000396000818161054f01528181611d8201526127d30152600081816105290152818161189f015261206e0152600081816102e001528181610ba901528181611a4801528181611b0201528181611b3601528181611b6901528181611bce01528181611c270152611cc90152600081816102470152818161029c01528181610708015281816121f10152818161276901526129be015261402e6000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610527578063e0351e131461054d578063e8a1da1714610573578063f2fde38b1461058657600080fd5b8063c0d78655146104d9578063c4bffe2b146104ec578063c75eea9c14610501578063cf7401f31461051457600080fd5b8063acfecf91116100de578063acfecf9114610426578063af58d59f14610439578063b0f479a1146104a8578063b7946580146104c657600080fd5b80639a4575b9146103d1578063a42a7b8b146103f1578063a7cd63b71461041157600080fd5b806354c8a4f31161017157806379ba50971161014b57806379ba5097146103855780637d54534e1461038d5780638926f54f146103a05780638da5cb5b146103b357600080fd5b806354c8a4f31461033f57806362ddd3c4146103545780636d3d1a581461036757600080fd5b8063240028e8116101ad578063240028e81461028c57806324f65ee7146102d9578063390775371461030a5780634c5ef0ed1461032c57600080fd5b806301ffc9a7146101d4578063181f5a77146101fc57806321df0da714610245575b600080fd5b6101e76101e236600461317e565b610599565b60405190151581526020015b60405180910390f35b6102386040518060400160405280601b81526020017f4275726e46726f6d4d696e74546f6b656e506f6f6c20312e352e31000000000081525081565b6040516101f39190613224565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b6101e761029a366004613259565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101f3565b61031d610318366004613276565b61067e565b604051905181526020016101f3565b6101e761033a3660046132cf565b61084d565b61035261034d36600461339e565b610897565b005b6103526103623660046132cf565b610912565b60095473ffffffffffffffffffffffffffffffffffffffff16610267565b6103526109af565b61035261039b366004613259565b610a7d565b6101e76103ae36600461340a565b610afe565b60015473ffffffffffffffffffffffffffffffffffffffff16610267565b6103e46103df366004613425565b610b15565b6040516101f39190613460565b6104046103ff36600461340a565b610bee565b6040516101f391906134b7565b610419610d59565b6040516101f39190613539565b6103526104343660046132cf565b610d6a565b61044c61044736600461340a565b610e82565b6040516101f3919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610267565b6102386104d436600461340a565b610f57565b6103526104e7366004613259565b611007565b6104f46110e2565b6040516101f39190613593565b61044c61050f36600461340a565b61119a565b61035261052236600461371b565b61126c565b7f0000000000000000000000000000000000000000000000000000000000000000610267565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b61035261058136600461339e565b6112f0565b610352610594366004613259565b611802565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067857507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60408051602081019091526000815261069682611816565b60006106ef60608401356106ea6106b060c0870187613760565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3a92505050565b611afe565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961073d6060860160408701613259565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107aa57600080fd5b505af11580156107be573d6000803e3d6000fd5b506107d3925050506060840160408501613259565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161083191815260200190565b60405180910390a3604080516020810190915290815292915050565b600061088f83836040516108629291906137c5565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611d12565b949350505050565b61089f611d2d565b61090c84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611d8092505050565b50505050565b61091a611d2d565b61092383610afe565b61096a576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109aa8383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3692505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a00576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a85611d2d565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610678600567ffffffffffffffff8416611d12565b6040805180820190915260608082526020820152610b3282612030565b610b3f82606001356121bc565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b998460200160208101906104d4919061340a565b8152602001610be66040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610c179060050161225e565b90506000815167ffffffffffffffff811115610c3557610c356135d5565b604051908082528060200260200182016040528015610c6857816020015b6060815260200190600190039081610c535790505b50905060005b8251811015610d515760086000848381518110610c8d57610c8d6137d5565b602002602001015181526020019081526020016000208054610cae90613804565b80601f0160208091040260200160405190810160405280929190818152602001828054610cda90613804565b8015610d275780601f10610cfc57610100808354040283529160200191610d27565b820191906000526020600020905b815481529060010190602001808311610d0a57829003601f168201915b5050505050828281518110610d3e57610d3e6137d5565b6020908102919091010152600101610c6e565b509392505050565b6060610d65600261225e565b905090565b610d72611d2d565b610d7b83610afe565b610dbd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b610dfd8282604051610dd09291906137c5565b604080519182900390912067ffffffffffffffff861660009081526007602052919091206005019061226b565b610e39578282826040517f74f23c7c000000000000000000000000000000000000000000000000000000008152600401610961939291906138a0565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610e759291906138c4565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261067890612277565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610f8290613804565b80601f0160208091040260200160405190810160405280929190818152602001828054610fae90613804565b8015610ffb5780601f10610fd057610100808354040283529160200191610ffb565b820191906000526020600020905b815481529060010190602001808311610fde57829003601f168201915b50505050509050919050565b61100f611d2d565b73ffffffffffffffffffffffffffffffffffffffff811661105c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110f0600561225e565b90506000815167ffffffffffffffff81111561110e5761110e6135d5565b604051908082528060200260200182016040528015611137578160200160208202803683370190505b50905060005b825181101561119357828181518110611158576111586137d5565b6020026020010151828281518110611172576111726137d5565b67ffffffffffffffff9092166020928302919091019091015260010161113d565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261067890612277565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906112ac575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112e5576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b6109aa838383612329565b6112f8611d2d565b60005b838110156114e5576000858583818110611317576113176137d5565b905060200201602081019061132c919061340a565b9050611343600567ffffffffffffffff831661226b565b611385576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b67ffffffffffffffff811660009081526007602052604081206113aa9060050161225e565b905060005b81518110156114165761140d8282815181106113cd576113cd6137d5565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161226b90919063ffffffff16565b506001016113af565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff0000000000000000000000000000000000000000009081168255600182018390556002820180549091169055600381018290559061147f6004830182613111565b6005820160008181611491828261314b565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506114d3915050565b60405180910390a150506001016112fb565b5060005b818110156117fb576000838383818110611505576115056137d5565b905060200281019061151791906138d8565b611520906139a4565b905061153181606001516000612413565b61154081608001516000612413565b80604001515160000361157f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516115979060059067ffffffffffffffff16612550565b6115dc5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610961565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a90910299909316171790941695909517909255909202909117600382015590820151600482019061175f9082613b1b565b5060005b8260200151518110156117a35761179b83600001518460200151838151811061178e5761178e6137d5565b6020026020010151611f36565b600101611763565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516117e99493929190613c35565b60405180910390a150506001016114e9565b5050505050565b61180a611d2d565b6118138161255c565b50565b61182961029a60a0830160808401613259565b6118885761183d60a0820160808301613259565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610961565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6118d4604084016020850161340a565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119699190613cce565b156119a0576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b86119b3604083016020840161340a565b612620565b6119d86119cb604083016020840161340a565b61033a60a0840184613760565b611a1d576119e960a0820182613760565b6040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016109619291906138c4565b611813611a30604083016020840161340a565b8260600135612746565b60008151600003611a6c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611aa957816040517f953576f70000000000000000000000000000000000000000000000000000000081526004016109619190613224565b600082806020019051810190611abf9190613ceb565b905060ff81111561067857826040517f953576f70000000000000000000000000000000000000000000000000000000081526004016109619190613224565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611b34575081610678565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611c1f576000611b8e7f000000000000000000000000000000000000000000000000000000000000000084613d33565b9050604d8160ff161115611c02576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610961565b611c0d81600a613e6c565b611c179085613e7b565b915050610678565b6000611c4b837f0000000000000000000000000000000000000000000000000000000000000000613d33565b9050604d8160ff161180611c925750611c6581600a613e6c565b611c8f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613e7b565b84115b15611cfd576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610961565b611d0881600a613e6c565b61088f9085613eb6565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d7e576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611dd7576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611e6d576000838281518110611df757611df76137d5565b60200260200101519050611e1581600261278d90919063ffffffff16565b15611e645760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611dda565b5060005b81518110156109aa576000828281518110611e8e57611e8e6137d5565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ed25750611f2e565b611edd6002826127af565b15611f2c5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611e71565b8051600003611f71576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611fa39060050182612550565b611fdd5782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610961929190613ecd565b6000818152600860205260409020611ff58382613b1b565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610e759190613224565b61204361029a60a0830160808401613259565b6120575761183d60a0820160808301613259565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6120a3604084016020850161340a565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612114573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121389190613cce565b1561216f576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6121876121826060830160408401613259565b6127d1565b61219f61219a604083016020840161340a565b612850565b6118136121b2604083016020840161340a565b826060013561299e565b6040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906379cc679090604401600060405180830381600087803b15801561224a57600080fd5b505af11580156117fb573d6000803e3d6000fd5b60606000611d26836129e2565b6000611d268383612a3d565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261230582606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426122e99190613ef0565b85608001516fffffffffffffffffffffffffffffffff16612b30565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61233283610afe565b612374576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b61237f826000612413565b67ffffffffffffffff831660009081526007602052604090206123a29083612b58565b6123ad816000612413565b67ffffffffffffffff831660009081526007602052604090206123d39060020182612b58565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161240693929190613f03565b60405180910390a1505050565b8151156124de5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612469575060408201516fffffffffffffffffffffffffffffffff16155b156124a257816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016109619190613f86565b80156124da576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612517575060208201516fffffffffffffffffffffffffffffffff1615155b156124da57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016109619190613f86565b6000611d268383612cfa565b3373ffffffffffffffffffffffffffffffffffffffff8216036125ab576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61262981610afe565b61266b576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156126ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270e9190613cce565b611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206124da90600201827f0000000000000000000000000000000000000000000000000000000000000000612d49565b6000611d268373ffffffffffffffffffffffffffffffffffffffff8416612a3d565b6000611d268373ffffffffffffffffffffffffffffffffffffffff8416612cfa565b7f000000000000000000000000000000000000000000000000000000000000000015611813576128026002826130cc565b611813576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610961565b61285981610afe565b61289b576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612914573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129389190613fc2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206124da90827f0000000000000000000000000000000000000000000000000000000000000000612d49565b606081600001805480602002602001604051908101604052809291908181526020018280548015610ffb57602002820191906000526020600020905b815481526020019060010190808311612a1e5750505050509050919050565b60008181526001830160205260408120548015612b26576000612a61600183613ef0565b8554909150600090612a7590600190613ef0565b9050808214612ada576000866000018281548110612a9557612a956137d5565b9060005260206000200154905080876000018481548110612ab857612ab86137d5565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612aeb57612aeb613fdf565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610678565b6000915050610678565b6000612b4f85612b408486613eb6565b612b4a908761400e565b6130fb565b95945050505050565b8154600090612b8190700100000000000000000000000000000000900463ffffffff1642613ef0565b90508015612c235760018301548354612bc9916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612b30565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612c49916fffffffffffffffffffffffffffffffff90811691166130fb565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612406908490613f86565b6000818152600183016020526040812054612d4157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610678565b506000610678565b825474010000000000000000000000000000000000000000900460ff161580612d70575081155b15612d7a57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612dc090700100000000000000000000000000000000900463ffffffff1642613ef0565b90508015612e805781831115612e02576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612e3c9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612b30565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612f375773ffffffffffffffffffffffffffffffffffffffff8416612edf576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610961565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610961565b8483101561304a5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612f7b9082613ef0565b612f85878a613ef0565b612f8f919061400e565b612f999190613e7b565b905073ffffffffffffffffffffffffffffffffffffffff8616612ff2576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610961565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610961565b6130548584613ef0565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611d26565b600081831061310a5781611d26565b5090919050565b50805461311d90613804565b6000825580601f1061312d575050565b601f0160209004906000526020600020908101906118139190613165565b508054600082559060005260206000209081019061181391905b5b8082111561317a5760008155600101613166565b5090565b60006020828403121561319057600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611d2657600080fd5b6000815180845260005b818110156131e6576020818501810151868301820152016131ca565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611d2660208301846131c0565b73ffffffffffffffffffffffffffffffffffffffff8116811461181357600080fd5b60006020828403121561326b57600080fd5b8135611d2681613237565b60006020828403121561328857600080fd5b813567ffffffffffffffff81111561329f57600080fd5b82016101008185031215611d2657600080fd5b803567ffffffffffffffff811681146132ca57600080fd5b919050565b6000806000604084860312156132e457600080fd5b6132ed846132b2565b9250602084013567ffffffffffffffff8082111561330a57600080fd5b818601915086601f83011261331e57600080fd5b81358181111561332d57600080fd5b87602082850101111561333f57600080fd5b6020830194508093505050509250925092565b60008083601f84011261336457600080fd5b50813567ffffffffffffffff81111561337c57600080fd5b6020830191508360208260051b850101111561339757600080fd5b9250929050565b600080600080604085870312156133b457600080fd5b843567ffffffffffffffff808211156133cc57600080fd5b6133d888838901613352565b909650945060208701359150808211156133f157600080fd5b506133fe87828801613352565b95989497509550505050565b60006020828403121561341c57600080fd5b611d26826132b2565b60006020828403121561343757600080fd5b813567ffffffffffffffff81111561344e57600080fd5b820160a08185031215611d2657600080fd5b60208152600082516040602084015261347c60608401826131c0565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612b4f82826131c0565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561352c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261351a8583516131c0565b945092850192908501906001016134e0565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358757835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613555565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358757835167ffffffffffffffff16835292840192918401916001016135af565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613627576136276135d5565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613674576136746135d5565b604052919050565b801515811461181357600080fd5b80356fffffffffffffffffffffffffffffffff811681146132ca57600080fd5b6000606082840312156136bc57600080fd5b6040516060810181811067ffffffffffffffff821117156136df576136df6135d5565b60405290508082356136f08161367c565b81526136fe6020840161368a565b602082015261370f6040840161368a565b60408201525092915050565b600080600060e0848603121561373057600080fd5b613739846132b2565b925061374885602086016136aa565b915061375785608086016136aa565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261379557600080fd5b83018035915067ffffffffffffffff8211156137b057600080fd5b60200191503681900382131561339757600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061381857607f821691505b602082108103613851577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612b4f604083018486613857565b60208152600061088f602083018486613857565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261390c57600080fd5b9190910192915050565b600082601f83011261392757600080fd5b813567ffffffffffffffff811115613941576139416135d5565b61397260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161362d565b81815284602083860101111561398757600080fd5b816020850160208301376000918101602001919091529392505050565b600061012082360312156139b757600080fd5b6139bf613604565b6139c8836132b2565b815260208084013567ffffffffffffffff808211156139e657600080fd5b9085019036601f8301126139f957600080fd5b813581811115613a0b57613a0b6135d5565b8060051b613a1a85820161362d565b9182528381018501918581019036841115613a3457600080fd5b86860192505b83831015613a7057823585811115613a525760008081fd5b613a603689838a0101613916565b8352509186019190860190613a3a565b8087890152505050506040860135925080831115613a8d57600080fd5b5050613a9b36828601613916565b604083015250613aae36606085016136aa565b6060820152613ac03660c085016136aa565b608082015292915050565b601f8211156109aa576000816000526020600020601f850160051c81016020861015613af45750805b601f850160051c820191505b81811015613b1357828155600101613b00565b505050505050565b815167ffffffffffffffff811115613b3557613b356135d5565b613b4981613b438454613804565b84613acb565b602080601f831160018114613b9c5760008415613b665750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b13565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613be957888601518255948401946001909101908401613bca565b5085821015613c2557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613c59818401876131c0565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613c979050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612b4f565b600060208284031215613ce057600080fd5b8151611d268161367c565b600060208284031215613cfd57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561067857610678613d04565b600181815b80851115613da557817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613d8b57613d8b613d04565b80851615613d9857918102915b93841c9390800290613d51565b509250929050565b600082613dbc57506001610678565b81613dc957506000610678565b8160018114613ddf5760028114613de957613e05565b6001915050610678565b60ff841115613dfa57613dfa613d04565b50506001821b610678565b5060208310610133831016604e8410600b8410161715613e28575081810a610678565b613e328383613d4c565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613e6457613e64613d04565b029392505050565b6000611d2660ff841683613dad565b600082613eb1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761067857610678613d04565b67ffffffffffffffff8316815260406020820152600061088f60408301846131c0565b8181038181111561067857610678613d04565b67ffffffffffffffff8416815260e08101613f4f60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c083015261088f565b6060810161067882848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613fd457600080fd5b8151611d2681613237565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561067857610678613d0456fea164736f6c6343000818000a", } var BurnFromMintTokenPoolABI = BurnFromMintTokenPoolMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go index 1a83c0a1cb6..ecfad493c2c 100644 --- a/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go @@ -81,8 +81,8 @@ type TokenPoolChainUpdate struct { } var BurnMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b506040516200460d3803806200460d8339810160408190526200003591620004f0565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f816200014b565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0385811660805282811660c05260ff851660a052600480546001600160a01b031916918316919091179055825115801560e0526200013b576040805160008152602081019091526200013b9084620001c5565b5050505050505050505062000669565b336001600160a01b038216036200017557604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e051620001e6576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002715760008382815181106200020a576200020a6200061b565b602090810291909101015190506200022460028262000322565b1562000267576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620001e9565b5060005b81518110156200031d5760008282815181106200029657620002966200061b565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002c2575062000314565b620002cf60028262000342565b1562000312576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000275565b505050565b600062000339836001600160a01b03841662000359565b90505b92915050565b600062000339836001600160a01b0384166200045d565b60008181526001830160205260408120548015620004525760006200038060018362000631565b8554909150600090620003969060019062000631565b905080821462000402576000866000018281548110620003ba57620003ba6200061b565b9060005260206000200154905080876000018481548110620003e057620003e06200061b565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000416576200041662000653565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200033c565b60009150506200033c565b6000818152600183016020526040812054620004a6575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200033c565b5060006200033c565b6001600160a01b0381168114620004c557600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620004eb81620004af565b919050565b600080600080600060a086880312156200050957600080fd5b85516200051681620004af565b8095505060208087015160ff811681146200053057600080fd5b60408801519095506001600160401b03808211156200054e57600080fd5b818901915089601f8301126200056357600080fd5b815181811115620005785762000578620004c8565b8060051b604051601f19603f83011681018181108582111715620005a057620005a0620004c8565b60405291825284820192508381018501918c831115620005bf57600080fd5b938501935b82851015620005e857620005d885620004de565b84529385019392850192620005c4565b809850505050505050620005ff60608701620004de565b91506200060f60808701620004de565b90509295509295909350565b634e487b7160e01b600052603260045260246000fd5b818103818111156200033c57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e051613f016200070c6000396000818161054f01528181611c5b01526126a60152600081816105290152818161189f0152611f470152600081816102e001528181610ba901528181611a4801528181611b0201528181611b3601528181611b670152611bae0152600081816102470152818161029c01528181610708015281816120c40152818161263c01526128910152613f016000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610527578063e0351e131461054d578063e8a1da1714610573578063f2fde38b1461058657600080fd5b8063c0d78655146104d9578063c4bffe2b146104ec578063c75eea9c14610501578063cf7401f31461051457600080fd5b8063acfecf91116100de578063acfecf9114610426578063af58d59f14610439578063b0f479a1146104a8578063b7946580146104c657600080fd5b80639a4575b9146103d1578063a42a7b8b146103f1578063a7cd63b71461041157600080fd5b806354c8a4f31161017157806379ba50971161014b57806379ba5097146103855780637d54534e1461038d5780638926f54f146103a05780638da5cb5b146103b357600080fd5b806354c8a4f31461033f57806362ddd3c4146103545780636d3d1a581461036757600080fd5b8063240028e8116101ad578063240028e81461028c57806324f65ee7146102d9578063390775371461030a5780634c5ef0ed1461032c57600080fd5b806301ffc9a7146101d4578063181f5a77146101fc57806321df0da714610245575b600080fd5b6101e76101e2366004613051565b610599565b60405190151581526020015b60405180910390f35b6102386040518060400160405280601781526020017f4275726e4d696e74546f6b656e506f6f6c20312e352e3100000000000000000081525081565b6040516101f391906130f7565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b6101e761029a36600461312c565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101f3565b61031d610318366004613149565b61067e565b604051905181526020016101f3565b6101e761033a3660046131a2565b61084d565b61035261034d366004613271565b610897565b005b6103526103623660046131a2565b610912565b60095473ffffffffffffffffffffffffffffffffffffffff16610267565b6103526109af565b61035261039b36600461312c565b610a7d565b6101e76103ae3660046132dd565b610afe565b60015473ffffffffffffffffffffffffffffffffffffffff16610267565b6103e46103df3660046132f8565b610b15565b6040516101f39190613333565b6104046103ff3660046132dd565b610bee565b6040516101f3919061338a565b610419610d59565b6040516101f3919061340c565b6103526104343660046131a2565b610d6a565b61044c6104473660046132dd565b610e82565b6040516101f3919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610267565b6102386104d43660046132dd565b610f57565b6103526104e736600461312c565b611007565b6104f46110e2565b6040516101f39190613466565b61044c61050f3660046132dd565b61119a565b6103526105223660046135ee565b61126c565b7f0000000000000000000000000000000000000000000000000000000000000000610267565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b610352610581366004613271565b6112f0565b61035261059436600461312c565b611802565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067857507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60408051602081019091526000815261069682611816565b60006106ef60608401356106ea6106b060c0870187613633565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3a92505050565b611afe565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961073d606086016040870161312c565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107aa57600080fd5b505af11580156107be573d6000803e3d6000fd5b506107d392505050606084016040850161312c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161083191815260200190565b60405180910390a3604080516020810190915290815292915050565b600061088f8383604051610862929190613698565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611bee565b949350505050565b61089f611c06565b61090c84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611c5992505050565b50505050565b61091a611c06565b61092383610afe565b61096a576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109aa8383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e0f92505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a00576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a85611c06565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610678600567ffffffffffffffff8416611bee565b6040805180820190915260608082526020820152610b3282611f09565b610b3f8260600135612095565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b998460200160208101906104d491906132dd565b8152602001610be66040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610c1790600501612131565b90506000815167ffffffffffffffff811115610c3557610c356134a8565b604051908082528060200260200182016040528015610c6857816020015b6060815260200190600190039081610c535790505b50905060005b8251811015610d515760086000848381518110610c8d57610c8d6136a8565b602002602001015181526020019081526020016000208054610cae906136d7565b80601f0160208091040260200160405190810160405280929190818152602001828054610cda906136d7565b8015610d275780601f10610cfc57610100808354040283529160200191610d27565b820191906000526020600020905b815481529060010190602001808311610d0a57829003601f168201915b5050505050828281518110610d3e57610d3e6136a8565b6020908102919091010152600101610c6e565b509392505050565b6060610d656002612131565b905090565b610d72611c06565b610d7b83610afe565b610dbd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b610dfd8282604051610dd0929190613698565b604080519182900390912067ffffffffffffffff861660009081526007602052919091206005019061213e565b610e39578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161096193929190613773565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610e75929190613797565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526106789061214a565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610f82906136d7565b80601f0160208091040260200160405190810160405280929190818152602001828054610fae906136d7565b8015610ffb5780601f10610fd057610100808354040283529160200191610ffb565b820191906000526020600020905b815481529060010190602001808311610fde57829003601f168201915b50505050509050919050565b61100f611c06565b73ffffffffffffffffffffffffffffffffffffffff811661105c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110f06005612131565b90506000815167ffffffffffffffff81111561110e5761110e6134a8565b604051908082528060200260200182016040528015611137578160200160208202803683370190505b50905060005b825181101561119357828181518110611158576111586136a8565b6020026020010151828281518110611172576111726136a8565b67ffffffffffffffff9092166020928302919091019091015260010161113d565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526106789061214a565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906112ac575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112e5576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b6109aa8383836121fc565b6112f8611c06565b60005b838110156114e5576000858583818110611317576113176136a8565b905060200201602081019061132c91906132dd565b9050611343600567ffffffffffffffff831661213e565b611385576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b67ffffffffffffffff811660009081526007602052604081206113aa90600501612131565b905060005b81518110156114165761140d8282815181106113cd576113cd6136a8565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161213e90919063ffffffff16565b506001016113af565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff0000000000000000000000000000000000000000009081168255600182018390556002820180549091169055600381018290559061147f6004830182612fe4565b6005820160008181611491828261301e565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506114d3915050565b60405180910390a150506001016112fb565b5060005b818110156117fb576000838383818110611505576115056136a8565b905060200281019061151791906137ab565b61152090613877565b9050611531816060015160006122e6565b611540816080015160006122e6565b80604001515160000361157f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516115979060059067ffffffffffffffff16612423565b6115dc5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610961565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a90910299909316171790941695909517909255909202909117600382015590820151600482019061175f90826139ee565b5060005b8260200151518110156117a35761179b83600001518460200151838151811061178e5761178e6136a8565b6020026020010151611e0f565b600101611763565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516117e99493929190613b08565b60405180910390a150506001016114e9565b5050505050565b61180a611c06565b6118138161242f565b50565b61182961029a60a083016080840161312c565b6118885761183d60a082016080830161312c565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610961565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6118d460408401602085016132dd565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119699190613ba1565b156119a0576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b86119b360408301602084016132dd565b6124f3565b6119d86119cb60408301602084016132dd565b61033a60a0840184613633565b611a1d576119e960a0820182613633565b6040517f24eb47e5000000000000000000000000000000000000000000000000000000008152600401610961929190613797565b611813611a3060408301602084016132dd565b8260600135612619565b60008151600003611a6c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611aa957816040517f953576f700000000000000000000000000000000000000000000000000000000815260040161096191906130f7565b600082806020019051810190611abf9190613bbe565b905060ff81111561067857826040517f953576f700000000000000000000000000000000000000000000000000000000815260040161096191906130f7565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611b34575081610678565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611ba857611b8c7f000000000000000000000000000000000000000000000000000000000000000083613c06565b611b9790600a613d3f565b611ba19084613d4e565b9050610678565b611bd2827f0000000000000000000000000000000000000000000000000000000000000000613c06565b611bdd90600a613d3f565b611be79084613d89565b9392505050565b60008181526001830160205260408120541515611be7565b60015473ffffffffffffffffffffffffffffffffffffffff163314611c57576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611cb0576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611d46576000838281518110611cd057611cd06136a8565b60200260200101519050611cee81600261266090919063ffffffff16565b15611d3d5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611cb3565b5060005b81518110156109aa576000828281518110611d6757611d676136a8565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611dab5750611e07565b611db6600282612682565b15611e055760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611d4a565b8051600003611e4a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611e7c9060050182612423565b611eb65782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610961929190613da0565b6000818152600860205260409020611ece83826139ee565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610e7591906130f7565b611f1c61029a60a083016080840161312c565b611f305761183d60a082016080830161312c565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611f7c60408401602085016132dd565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611fed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120119190613ba1565b15612048576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61206061205b606083016040840161312c565b6126a4565b61207861207360408301602084016132dd565b612723565b61181361208b60408301602084016132dd565b8260600135612871565b6040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b15801561211d57600080fd5b505af11580156117fb573d6000803e3d6000fd5b60606000611be7836128b5565b6000611be78383612910565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526121d882606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426121bc9190613dc3565b85608001516fffffffffffffffffffffffffffffffff16612a03565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61220583610afe565b612247576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b6122528260006122e6565b67ffffffffffffffff831660009081526007602052604090206122759083612a2b565b6122808160006122e6565b67ffffffffffffffff831660009081526007602052604090206122a69060020182612a2b565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516122d993929190613dd6565b60405180910390a1505050565b8151156123b15781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff1610158061233c575060408201516fffffffffffffffffffffffffffffffff16155b1561237557816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016109619190613e59565b80156123ad576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff161515806123ea575060208201516fffffffffffffffffffffffffffffffff1615155b156123ad57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016109619190613e59565b6000611be78383612bcd565b3373ffffffffffffffffffffffffffffffffffffffff82160361247e576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6124fc81610afe565b61253e576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613ba1565b611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206123ad90600201827f0000000000000000000000000000000000000000000000000000000000000000612c1c565b6000611be78373ffffffffffffffffffffffffffffffffffffffff8416612910565b6000611be78373ffffffffffffffffffffffffffffffffffffffff8416612bcd565b7f000000000000000000000000000000000000000000000000000000000000000015611813576126d5600282612f9f565b611813576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610961565b61272c81610afe565b61276e576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa1580156127e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280b9190613e95565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206123ad90827f0000000000000000000000000000000000000000000000000000000000000000612c1c565b606081600001805480602002602001604051908101604052809291908181526020018280548015610ffb57602002820191906000526020600020905b8154815260200190600101908083116128f15750505050509050919050565b600081815260018301602052604081205480156129f9576000612934600183613dc3565b855490915060009061294890600190613dc3565b90508082146129ad576000866000018281548110612968576129686136a8565b906000526020600020015490508087600001848154811061298b5761298b6136a8565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806129be576129be613eb2565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610678565b6000915050610678565b6000612a2285612a138486613d89565b612a1d9087613ee1565b612fce565b95945050505050565b8154600090612a5490700100000000000000000000000000000000900463ffffffff1642613dc3565b90508015612af65760018301548354612a9c916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612a03565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612b1c916fffffffffffffffffffffffffffffffff9081169116612fce565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906122d9908490613e59565b6000818152600183016020526040812054612c1457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610678565b506000610678565b825474010000000000000000000000000000000000000000900460ff161580612c43575081155b15612c4d57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612c9390700100000000000000000000000000000000900463ffffffff1642613dc3565b90508015612d535781831115612cd5576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612d0f9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612a03565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612e0a5773ffffffffffffffffffffffffffffffffffffffff8416612db2576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610961565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610961565b84831015612f1d5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612e4e9082613dc3565b612e58878a613dc3565b612e629190613ee1565b612e6c9190613d4e565b905073ffffffffffffffffffffffffffffffffffffffff8616612ec5576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610961565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610961565b612f278584613dc3565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611be7565b6000818310612fdd5781611be7565b5090919050565b508054612ff0906136d7565b6000825580601f10613000575050565b601f0160209004906000526020600020908101906118139190613038565b508054600082559060005260206000209081019061181391905b5b8082111561304d5760008155600101613039565b5090565b60006020828403121561306357600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611be757600080fd5b6000815180845260005b818110156130b95760208185018101518683018201520161309d565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611be76020830184613093565b73ffffffffffffffffffffffffffffffffffffffff8116811461181357600080fd5b60006020828403121561313e57600080fd5b8135611be78161310a565b60006020828403121561315b57600080fd5b813567ffffffffffffffff81111561317257600080fd5b82016101008185031215611be757600080fd5b803567ffffffffffffffff8116811461319d57600080fd5b919050565b6000806000604084860312156131b757600080fd5b6131c084613185565b9250602084013567ffffffffffffffff808211156131dd57600080fd5b818601915086601f8301126131f157600080fd5b81358181111561320057600080fd5b87602082850101111561321257600080fd5b6020830194508093505050509250925092565b60008083601f84011261323757600080fd5b50813567ffffffffffffffff81111561324f57600080fd5b6020830191508360208260051b850101111561326a57600080fd5b9250929050565b6000806000806040858703121561328757600080fd5b843567ffffffffffffffff8082111561329f57600080fd5b6132ab88838901613225565b909650945060208701359150808211156132c457600080fd5b506132d187828801613225565b95989497509550505050565b6000602082840312156132ef57600080fd5b611be782613185565b60006020828403121561330a57600080fd5b813567ffffffffffffffff81111561332157600080fd5b820160a08185031215611be757600080fd5b60208152600082516040602084015261334f6060840182613093565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612a228282613093565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156133ff577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526133ed858351613093565b945092850192908501906001016133b3565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561345a57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613428565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561345a57835167ffffffffffffffff1683529284019291840191600101613482565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156134fa576134fa6134a8565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613547576135476134a8565b604052919050565b801515811461181357600080fd5b80356fffffffffffffffffffffffffffffffff8116811461319d57600080fd5b60006060828403121561358f57600080fd5b6040516060810181811067ffffffffffffffff821117156135b2576135b26134a8565b60405290508082356135c38161354f565b81526135d16020840161355d565b60208201526135e26040840161355d565b60408201525092915050565b600080600060e0848603121561360357600080fd5b61360c84613185565b925061361b856020860161357d565b915061362a856080860161357d565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261366857600080fd5b83018035915067ffffffffffffffff82111561368357600080fd5b60200191503681900382131561326a57600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c908216806136eb57607f821691505b602082108103613724577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612a2260408301848661372a565b60208152600061088f60208301848661372a565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181126137df57600080fd5b9190910192915050565b600082601f8301126137fa57600080fd5b813567ffffffffffffffff811115613814576138146134a8565b61384560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613500565b81815284602083860101111561385a57600080fd5b816020850160208301376000918101602001919091529392505050565b6000610120823603121561388a57600080fd5b6138926134d7565b61389b83613185565b815260208084013567ffffffffffffffff808211156138b957600080fd5b9085019036601f8301126138cc57600080fd5b8135818111156138de576138de6134a8565b8060051b6138ed858201613500565b918252838101850191858101903684111561390757600080fd5b86860192505b83831015613943578235858111156139255760008081fd5b6139333689838a01016137e9565b835250918601919086019061390d565b808789015250505050604086013592508083111561396057600080fd5b505061396e368286016137e9565b604083015250613981366060850161357d565b60608201526139933660c0850161357d565b608082015292915050565b601f8211156109aa576000816000526020600020601f850160051c810160208610156139c75750805b601f850160051c820191505b818110156139e6578281556001016139d3565b505050505050565b815167ffffffffffffffff811115613a0857613a086134a8565b613a1c81613a1684546136d7565b8461399e565b602080601f831160018114613a6f5760008415613a395750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556139e6565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613abc57888601518255948401946001909101908401613a9d565b5085821015613af857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613b2c81840187613093565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613b6a9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612a22565b600060208284031215613bb357600080fd5b8151611be78161354f565b600060208284031215613bd057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561067857610678613bd7565b600181815b80851115613c7857817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613c5e57613c5e613bd7565b80851615613c6b57918102915b93841c9390800290613c24565b509250929050565b600082613c8f57506001610678565b81613c9c57506000610678565b8160018114613cb25760028114613cbc57613cd8565b6001915050610678565b60ff841115613ccd57613ccd613bd7565b50506001821b610678565b5060208310610133831016604e8410600b8410161715613cfb575081810a610678565b613d058383613c1f565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613d3757613d37613bd7565b029392505050565b6000611be760ff841683613c80565b600082613d84577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761067857610678613bd7565b67ffffffffffffffff8316815260406020820152600061088f6040830184613093565b8181038181111561067857610678613bd7565b67ffffffffffffffff8416815260e08101613e2260208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c083015261088f565b6060810161067882848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613ea757600080fd5b8151611be78161310a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561067857610678613bd756fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b5060405162004809380380620048098339810160408190526200003591620005a2565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f81620001eb565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e91810190620006c4565b60015b1562000191578060ff168560ff16146200018f576040516332ad3e0760e11b815260ff80871660048301528216602482015260440160405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001db57604080516000815260208101909152620001db908462000265565b5050505050505050505062000730565b336001600160a01b038216036200021557604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e05162000286576040516335f4a7b360e01b815260040160405180910390fd5b60005b825181101562000311576000838281518110620002aa57620002aa620006e2565b60209081029190910101519050620002c4600282620003c2565b1562000307576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000289565b5060005b8151811015620003bd576000828281518110620003365762000336620006e2565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003625750620003b4565b6200036f600282620003e2565b15620003b2576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000315565b505050565b6000620003d9836001600160a01b038416620003f9565b90505b92915050565b6000620003d9836001600160a01b038416620004fd565b60008181526001830160205260408120548015620004f257600062000420600183620006f8565b85549091506000906200043690600190620006f8565b9050808214620004a25760008660000182815481106200045a576200045a620006e2565b9060005260206000200154905080876000018481548110620004805762000480620006e2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004b657620004b66200071a565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003dc565b6000915050620003dc565b60008181526001830160205260408120546200054657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003dc565b506000620003dc565b6001600160a01b03811681146200056557600080fd5b50565b805160ff811681146200057a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b80516200057a816200054f565b600080600080600060a08688031215620005bb57600080fd5b8551620005c8816200054f565b94506020620005d987820162000568565b60408801519095506001600160401b0380821115620005f757600080fd5b818901915089601f8301126200060c57600080fd5b8151818111156200062157620006216200057f565b8060051b604051601f19603f830116810181811085821117156200064957620006496200057f565b60405291825284820192508381018501918c8311156200066857600080fd5b938501935b828510156200069157620006818562000595565b845293850193928501926200066d565b809850505050505050620006a86060870162000595565b9150620006b86080870162000595565b90509295509295909350565b600060208284031215620006d757600080fd5b620003d98262000568565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003dc57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e051614028620007e16000396000818161054f01528181611d8201526127cd0152600081816105290152818161189f015261206e0152600081816102e001528181610ba901528181611a4801528181611b0201528181611b3601528181611b6901528181611bce01528181611c270152611cc90152600081816102470152818161029c01528181610708015281816121eb0152818161276301526129b801526140286000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610527578063e0351e131461054d578063e8a1da1714610573578063f2fde38b1461058657600080fd5b8063c0d78655146104d9578063c4bffe2b146104ec578063c75eea9c14610501578063cf7401f31461051457600080fd5b8063acfecf91116100de578063acfecf9114610426578063af58d59f14610439578063b0f479a1146104a8578063b7946580146104c657600080fd5b80639a4575b9146103d1578063a42a7b8b146103f1578063a7cd63b71461041157600080fd5b806354c8a4f31161017157806379ba50971161014b57806379ba5097146103855780637d54534e1461038d5780638926f54f146103a05780638da5cb5b146103b357600080fd5b806354c8a4f31461033f57806362ddd3c4146103545780636d3d1a581461036757600080fd5b8063240028e8116101ad578063240028e81461028c57806324f65ee7146102d9578063390775371461030a5780634c5ef0ed1461032c57600080fd5b806301ffc9a7146101d4578063181f5a77146101fc57806321df0da714610245575b600080fd5b6101e76101e2366004613178565b610599565b60405190151581526020015b60405180910390f35b6102386040518060400160405280601781526020017f4275726e4d696e74546f6b656e506f6f6c20312e352e3100000000000000000081525081565b6040516101f3919061321e565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b6101e761029a366004613253565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101f3565b61031d610318366004613270565b61067e565b604051905181526020016101f3565b6101e761033a3660046132c9565b61084d565b61035261034d366004613398565b610897565b005b6103526103623660046132c9565b610912565b60095473ffffffffffffffffffffffffffffffffffffffff16610267565b6103526109af565b61035261039b366004613253565b610a7d565b6101e76103ae366004613404565b610afe565b60015473ffffffffffffffffffffffffffffffffffffffff16610267565b6103e46103df36600461341f565b610b15565b6040516101f3919061345a565b6104046103ff366004613404565b610bee565b6040516101f391906134b1565b610419610d59565b6040516101f39190613533565b6103526104343660046132c9565b610d6a565b61044c610447366004613404565b610e82565b6040516101f3919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610267565b6102386104d4366004613404565b610f57565b6103526104e7366004613253565b611007565b6104f46110e2565b6040516101f3919061358d565b61044c61050f366004613404565b61119a565b610352610522366004613715565b61126c565b7f0000000000000000000000000000000000000000000000000000000000000000610267565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b610352610581366004613398565b6112f0565b610352610594366004613253565b611802565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067857507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60408051602081019091526000815261069682611816565b60006106ef60608401356106ea6106b060c087018761375a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3a92505050565b611afe565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961073d6060860160408701613253565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107aa57600080fd5b505af11580156107be573d6000803e3d6000fd5b506107d3925050506060840160408501613253565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161083191815260200190565b60405180910390a3604080516020810190915290815292915050565b600061088f83836040516108629291906137bf565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611d12565b949350505050565b61089f611d2d565b61090c84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611d8092505050565b50505050565b61091a611d2d565b61092383610afe565b61096a576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109aa8383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3692505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a00576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a85611d2d565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610678600567ffffffffffffffff8416611d12565b6040805180820190915260608082526020820152610b3282612030565b610b3f82606001356121bc565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b998460200160208101906104d49190613404565b8152602001610be66040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610c1790600501612258565b90506000815167ffffffffffffffff811115610c3557610c356135cf565b604051908082528060200260200182016040528015610c6857816020015b6060815260200190600190039081610c535790505b50905060005b8251811015610d515760086000848381518110610c8d57610c8d6137cf565b602002602001015181526020019081526020016000208054610cae906137fe565b80601f0160208091040260200160405190810160405280929190818152602001828054610cda906137fe565b8015610d275780601f10610cfc57610100808354040283529160200191610d27565b820191906000526020600020905b815481529060010190602001808311610d0a57829003601f168201915b5050505050828281518110610d3e57610d3e6137cf565b6020908102919091010152600101610c6e565b509392505050565b6060610d656002612258565b905090565b610d72611d2d565b610d7b83610afe565b610dbd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b610dfd8282604051610dd09291906137bf565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190612265565b610e39578282826040517f74f23c7c0000000000000000000000000000000000000000000000000000000081526004016109619392919061389a565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610e759291906138be565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261067890612271565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610f82906137fe565b80601f0160208091040260200160405190810160405280929190818152602001828054610fae906137fe565b8015610ffb5780601f10610fd057610100808354040283529160200191610ffb565b820191906000526020600020905b815481529060010190602001808311610fde57829003601f168201915b50505050509050919050565b61100f611d2d565b73ffffffffffffffffffffffffffffffffffffffff811661105c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110f06005612258565b90506000815167ffffffffffffffff81111561110e5761110e6135cf565b604051908082528060200260200182016040528015611137578160200160208202803683370190505b50905060005b825181101561119357828181518110611158576111586137cf565b6020026020010151828281518110611172576111726137cf565b67ffffffffffffffff9092166020928302919091019091015260010161113d565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261067890612271565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906112ac575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112e5576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b6109aa838383612323565b6112f8611d2d565b60005b838110156114e5576000858583818110611317576113176137cf565b905060200201602081019061132c9190613404565b9050611343600567ffffffffffffffff8316612265565b611385576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b67ffffffffffffffff811660009081526007602052604081206113aa90600501612258565b905060005b81518110156114165761140d8282815181106113cd576113cd6137cf565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161226590919063ffffffff16565b506001016113af565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff0000000000000000000000000000000000000000009081168255600182018390556002820180549091169055600381018290559061147f600483018261310b565b60058201600081816114918282613145565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506114d3915050565b60405180910390a150506001016112fb565b5060005b818110156117fb576000838383818110611505576115056137cf565b905060200281019061151791906138d2565b6115209061399e565b90506115318160600151600061240d565b6115408160800151600061240d565b80604001515160000361157f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516115979060059067ffffffffffffffff1661254a565b6115dc5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610961565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a90910299909316171790941695909517909255909202909117600382015590820151600482019061175f9082613b15565b5060005b8260200151518110156117a35761179b83600001518460200151838151811061178e5761178e6137cf565b6020026020010151611f36565b600101611763565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516117e99493929190613c2f565b60405180910390a150506001016114e9565b5050505050565b61180a611d2d565b61181381612556565b50565b61182961029a60a0830160808401613253565b6118885761183d60a0820160808301613253565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610961565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6118d46040840160208501613404565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119699190613cc8565b156119a0576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b86119b36040830160208401613404565b61261a565b6119d86119cb6040830160208401613404565b61033a60a084018461375a565b611a1d576119e960a082018261375a565b6040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016109619291906138be565b611813611a306040830160208401613404565b8260600135612740565b60008151600003611a6c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611aa957816040517f953576f7000000000000000000000000000000000000000000000000000000008152600401610961919061321e565b600082806020019051810190611abf9190613ce5565b905060ff81111561067857826040517f953576f7000000000000000000000000000000000000000000000000000000008152600401610961919061321e565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611b34575081610678565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611c1f576000611b8e7f000000000000000000000000000000000000000000000000000000000000000084613d2d565b9050604d8160ff161115611c02576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610961565b611c0d81600a613e66565b611c179085613e75565b915050610678565b6000611c4b837f0000000000000000000000000000000000000000000000000000000000000000613d2d565b9050604d8160ff161180611c925750611c6581600a613e66565b611c8f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613e75565b84115b15611cfd576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610961565b611d0881600a613e66565b61088f9085613eb0565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d7e576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611dd7576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611e6d576000838281518110611df757611df76137cf565b60200260200101519050611e1581600261278790919063ffffffff16565b15611e645760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611dda565b5060005b81518110156109aa576000828281518110611e8e57611e8e6137cf565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ed25750611f2e565b611edd6002826127a9565b15611f2c5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611e71565b8051600003611f71576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611fa3906005018261254a565b611fdd5782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610961929190613ec7565b6000818152600860205260409020611ff58382613b15565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610e75919061321e565b61204361029a60a0830160808401613253565b6120575761183d60a0820160808301613253565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6120a36040840160208501613404565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612114573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121389190613cc8565b1561216f576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6121876121826060830160408401613253565b6127cb565b61219f61219a6040830160208401613404565b61284a565b6118136121b26040830160208401613404565b8260600135612998565b6040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b15801561224457600080fd5b505af11580156117fb573d6000803e3d6000fd5b60606000611d26836129dc565b6000611d268383612a37565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526122ff82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426122e39190613eea565b85608001516fffffffffffffffffffffffffffffffff16612b2a565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61232c83610afe565b61236e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b61237982600061240d565b67ffffffffffffffff8316600090815260076020526040902061239c9083612b52565b6123a781600061240d565b67ffffffffffffffff831660009081526007602052604090206123cd9060020182612b52565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161240093929190613efd565b60405180910390a1505050565b8151156124d85781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612463575060408201516fffffffffffffffffffffffffffffffff16155b1561249c57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016109619190613f80565b80156124d4576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612511575060208201516fffffffffffffffffffffffffffffffff1615155b156124d457816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016109619190613f80565b6000611d268383612cf4565b3373ffffffffffffffffffffffffffffffffffffffff8216036125a5576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61262381610afe565b612665576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156126e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127089190613cc8565b611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206124d490600201827f0000000000000000000000000000000000000000000000000000000000000000612d43565b6000611d268373ffffffffffffffffffffffffffffffffffffffff8416612a37565b6000611d268373ffffffffffffffffffffffffffffffffffffffff8416612cf4565b7f000000000000000000000000000000000000000000000000000000000000000015611813576127fc6002826130c6565b611813576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610961565b61285381610afe565b612895576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561290e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129329190613fbc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206124d490827f0000000000000000000000000000000000000000000000000000000000000000612d43565b606081600001805480602002602001604051908101604052809291908181526020018280548015610ffb57602002820191906000526020600020905b815481526020019060010190808311612a185750505050509050919050565b60008181526001830160205260408120548015612b20576000612a5b600183613eea565b8554909150600090612a6f90600190613eea565b9050808214612ad4576000866000018281548110612a8f57612a8f6137cf565b9060005260206000200154905080876000018481548110612ab257612ab26137cf565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ae557612ae5613fd9565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610678565b6000915050610678565b6000612b4985612b3a8486613eb0565b612b449087614008565b6130f5565b95945050505050565b8154600090612b7b90700100000000000000000000000000000000900463ffffffff1642613eea565b90508015612c1d5760018301548354612bc3916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612b2a565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612c43916fffffffffffffffffffffffffffffffff90811691166130f5565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612400908490613f80565b6000818152600183016020526040812054612d3b57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610678565b506000610678565b825474010000000000000000000000000000000000000000900460ff161580612d6a575081155b15612d7457505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612dba90700100000000000000000000000000000000900463ffffffff1642613eea565b90508015612e7a5781831115612dfc576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612e369083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612b2a565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612f315773ffffffffffffffffffffffffffffffffffffffff8416612ed9576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610961565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610961565b848310156130445760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612f759082613eea565b612f7f878a613eea565b612f899190614008565b612f939190613e75565b905073ffffffffffffffffffffffffffffffffffffffff8616612fec576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610961565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610961565b61304e8584613eea565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611d26565b60008183106131045781611d26565b5090919050565b508054613117906137fe565b6000825580601f10613127575050565b601f016020900490600052602060002090810190611813919061315f565b508054600082559060005260206000209081019061181391905b5b808211156131745760008155600101613160565b5090565b60006020828403121561318a57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611d2657600080fd5b6000815180845260005b818110156131e0576020818501810151868301820152016131c4565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611d2660208301846131ba565b73ffffffffffffffffffffffffffffffffffffffff8116811461181357600080fd5b60006020828403121561326557600080fd5b8135611d2681613231565b60006020828403121561328257600080fd5b813567ffffffffffffffff81111561329957600080fd5b82016101008185031215611d2657600080fd5b803567ffffffffffffffff811681146132c457600080fd5b919050565b6000806000604084860312156132de57600080fd5b6132e7846132ac565b9250602084013567ffffffffffffffff8082111561330457600080fd5b818601915086601f83011261331857600080fd5b81358181111561332757600080fd5b87602082850101111561333957600080fd5b6020830194508093505050509250925092565b60008083601f84011261335e57600080fd5b50813567ffffffffffffffff81111561337657600080fd5b6020830191508360208260051b850101111561339157600080fd5b9250929050565b600080600080604085870312156133ae57600080fd5b843567ffffffffffffffff808211156133c657600080fd5b6133d28883890161334c565b909650945060208701359150808211156133eb57600080fd5b506133f88782880161334c565b95989497509550505050565b60006020828403121561341657600080fd5b611d26826132ac565b60006020828403121561343157600080fd5b813567ffffffffffffffff81111561344857600080fd5b820160a08185031215611d2657600080fd5b60208152600082516040602084015261347660608401826131ba565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612b4982826131ba565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613526577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526135148583516131ba565b945092850192908501906001016134da565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358157835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161354f565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358157835167ffffffffffffffff16835292840192918401916001016135a9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613621576136216135cf565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561366e5761366e6135cf565b604052919050565b801515811461181357600080fd5b80356fffffffffffffffffffffffffffffffff811681146132c457600080fd5b6000606082840312156136b657600080fd5b6040516060810181811067ffffffffffffffff821117156136d9576136d96135cf565b60405290508082356136ea81613676565b81526136f860208401613684565b602082015261370960408401613684565b60408201525092915050565b600080600060e0848603121561372a57600080fd5b613733846132ac565b925061374285602086016136a4565b915061375185608086016136a4565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261378f57600080fd5b83018035915067ffffffffffffffff8211156137aa57600080fd5b60200191503681900382131561339157600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061381257607f821691505b60208210810361384b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612b49604083018486613851565b60208152600061088f602083018486613851565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261390657600080fd5b9190910192915050565b600082601f83011261392157600080fd5b813567ffffffffffffffff81111561393b5761393b6135cf565b61396c60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613627565b81815284602083860101111561398157600080fd5b816020850160208301376000918101602001919091529392505050565b600061012082360312156139b157600080fd5b6139b96135fe565b6139c2836132ac565b815260208084013567ffffffffffffffff808211156139e057600080fd5b9085019036601f8301126139f357600080fd5b813581811115613a0557613a056135cf565b8060051b613a14858201613627565b9182528381018501918581019036841115613a2e57600080fd5b86860192505b83831015613a6a57823585811115613a4c5760008081fd5b613a5a3689838a0101613910565b8352509186019190860190613a34565b8087890152505050506040860135925080831115613a8757600080fd5b5050613a9536828601613910565b604083015250613aa836606085016136a4565b6060820152613aba3660c085016136a4565b608082015292915050565b601f8211156109aa576000816000526020600020601f850160051c81016020861015613aee5750805b601f850160051c820191505b81811015613b0d57828155600101613afa565b505050505050565b815167ffffffffffffffff811115613b2f57613b2f6135cf565b613b4381613b3d84546137fe565b84613ac5565b602080601f831160018114613b965760008415613b605750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b0d565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613be357888601518255948401946001909101908401613bc4565b5085821015613c1f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613c53818401876131ba565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613c919050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612b49565b600060208284031215613cda57600080fd5b8151611d2681613676565b600060208284031215613cf757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561067857610678613cfe565b600181815b80851115613d9f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613d8557613d85613cfe565b80851615613d9257918102915b93841c9390800290613d4b565b509250929050565b600082613db657506001610678565b81613dc357506000610678565b8160018114613dd95760028114613de357613dff565b6001915050610678565b60ff841115613df457613df4613cfe565b50506001821b610678565b5060208310610133831016604e8410600b8410161715613e22575081810a610678565b613e2c8383613d46565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613e5e57613e5e613cfe565b029392505050565b6000611d2660ff841683613da7565b600082613eab577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761067857610678613cfe565b67ffffffffffffffff8316815260406020820152600061088f60408301846131ba565b8181038181111561067857610678613cfe565b67ffffffffffffffff8416815260e08101613f4960208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c083015261088f565b6060810161067882848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613fce57600080fd5b8151611d2681613231565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561067857610678613cfe56fea164736f6c6343000818000a", } var BurnMintTokenPoolABI = BurnMintTokenPoolMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go index 2343828e892..7315989c076 100644 --- a/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go @@ -81,8 +81,8 @@ type TokenPoolChainUpdate struct { } var BurnWithFromMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b5060405162004a6338038062004a63833981016040819052620000359162000869565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000165565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0385811660805282811660c05260ff851660a052600480546001600160a01b031916918316919091179055825115801560e0526200013b576040805160008152602081019091526200013b9084620001df565b506200015a935050506001600160a01b0387169050306000196200033c565b505050505062000ac0565b336001600160a01b038216036200018f57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e05162000200576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200028b57600083828151811062000224576200022462000994565b602090810291909101015190506200023e60028262000422565b1562000281576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000203565b5060005b815181101562000337576000828281518110620002b057620002b062000994565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002dc57506200032e565b620002e960028262000442565b156200032c576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b6001016200028f565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200038e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003b49190620009aa565b620003c09190620009da565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200041c918691906200045916565b50505050565b600062000439836001600160a01b0384166200052e565b90505b92915050565b600062000439836001600160a01b03841662000632565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490820152600090620004a8906001600160a01b03851690849062000684565b805190915015620003375780806020019051810190620004c99190620009f0565b620003375760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084015b60405180910390fd5b60008181526001830160205260408120548015620006275760006200055560018362000a1b565b85549091506000906200056b9060019062000a1b565b9050808214620005d75760008660000182815481106200058f576200058f62000994565b9060005260206000200154905080876000018481548110620005b557620005b562000994565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620005eb57620005eb62000a31565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200043c565b60009150506200043c565b60008181526001830160205260408120546200067b575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200043c565b5060006200043c565b60606200069584846000856200069d565b949350505050565b606082471015620007005760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000525565b600080866001600160a01b031685876040516200071e919062000a6d565b60006040518083038185875af1925050503d80600081146200075d576040519150601f19603f3d011682016040523d82523d6000602084013e62000762565b606091505b509092509050620007768783838762000781565b979650505050505050565b60608315620007f5578251600003620007ed576001600160a01b0385163b620007ed5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000525565b508162000695565b6200069583838151156200080c5781518083602001fd5b8060405162461bcd60e51b815260040162000525919062000a8b565b6001600160a01b03811681146200083e57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620008648162000828565b919050565b600080600080600060a086880312156200088257600080fd5b85516200088f8162000828565b8095505060208087015160ff81168114620008a957600080fd5b60408801519095506001600160401b0380821115620008c757600080fd5b818901915089601f830112620008dc57600080fd5b815181811115620008f157620008f162000841565b8060051b604051601f19603f8301168101818110858211171562000919576200091962000841565b60405291825284820192508381018501918c8311156200093857600080fd5b938501935b828510156200096157620009518562000857565b845293850193928501926200093d565b809850505050505050620009786060870162000857565b9150620009886080870162000857565b90509295509295909350565b634e487b7160e01b600052603260045260246000fd5b600060208284031215620009bd57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156200043c576200043c620009c4565b60006020828403121562000a0357600080fd5b8151801515811462000a1457600080fd5b9392505050565b818103818111156200043c576200043c620009c4565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000a6457818101518382015260200162000a4a565b50506000910152565b6000825162000a8181846020870162000a47565b9190910192915050565b602081526000825180602084015262000aac81604085016020870162000a47565b601f01601f19169190910160400192915050565b60805160a05160c05160e051613f0062000b636000396000818161054801528181611c5401526126a5015260008181610522015281816118980152611f400152600081816102d901528181610ba201528181611a4101528181611afb01528181611b2f01528181611b600152611ba70152600081816102400152818161029501528181610701015281816120c30152818161263b01526128900152613f006000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610520578063e0351e1314610546578063e8a1da171461056c578063f2fde38b1461057f57600080fd5b8063c0d78655146104d2578063c4bffe2b146104e5578063c75eea9c146104fa578063cf7401f31461050d57600080fd5b8063acfecf91116100de578063acfecf911461041f578063af58d59f14610432578063b0f479a1146104a1578063b7946580146104bf57600080fd5b80639a4575b9146103ca578063a42a7b8b146103ea578063a7cd63b71461040a57600080fd5b806354c8a4f31161017157806379ba50971161014b57806379ba50971461037e5780637d54534e146103865780638926f54f146103995780638da5cb5b146103ac57600080fd5b806354c8a4f31461033857806362ddd3c41461034d5780636d3d1a581461036057600080fd5b8063240028e8116101ad578063240028e81461028557806324f65ee7146102d257806339077537146103035780634c5ef0ed1461032557600080fd5b806301ffc9a7146101d4578063181f5a77146101fc57806321df0da71461023e575b600080fd5b6101e76101e2366004613050565b610592565b60405190151581526020015b60405180910390f35b60408051808201909152601f81527f4275726e5769746846726f6d4d696e74546f6b656e506f6f6c20312e352e310060208201525b6040516101f391906130f6565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b6101e761029336600461312b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101f3565b610316610311366004613148565b610677565b604051905181526020016101f3565b6101e76103333660046131a1565b610846565b61034b610346366004613270565b610890565b005b61034b61035b3660046131a1565b61090b565b60095473ffffffffffffffffffffffffffffffffffffffff16610260565b61034b6109a8565b61034b61039436600461312b565b610a76565b6101e76103a73660046132dc565b610af7565b60015473ffffffffffffffffffffffffffffffffffffffff16610260565b6103dd6103d83660046132f7565b610b0e565b6040516101f39190613332565b6103fd6103f83660046132dc565b610be7565b6040516101f39190613389565b610412610d52565b6040516101f3919061340b565b61034b61042d3660046131a1565b610d63565b6104456104403660046132dc565b610e7b565b6040516101f3919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610260565b6102316104cd3660046132dc565b610f50565b61034b6104e036600461312b565b611000565b6104ed6110db565b6040516101f39190613465565b6104456105083660046132dc565b611193565b61034b61051b3660046135ed565b611265565b7f0000000000000000000000000000000000000000000000000000000000000000610260565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b61034b61057a366004613270565b6112e9565b61034b61058d36600461312b565b6117fb565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062557507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60408051602081019091526000815261068f8261180f565b60006106e860608401356106e36106a960c0870187613632565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3392505050565b611af7565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f19610736606086016040870161312b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107a357600080fd5b505af11580156107b7573d6000803e3d6000fd5b506107cc92505050606084016040850161312b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161082a91815260200190565b60405180910390a3604080516020810190915290815292915050565b6000610888838360405161085b929190613697565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611be7565b949350505050565b610898611bff565b61090584848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611c5292505050565b50505050565b610913611bff565b61091c83610af7565b610963576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109a38383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e0892505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109f9576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a7e611bff565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610671600567ffffffffffffffff8416611be7565b6040805180820190915260608082526020820152610b2b82611f02565b610b38826060013561208e565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b928460200160208101906104cd91906132dc565b8152602001610bdf6040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610c1090600501612130565b90506000815167ffffffffffffffff811115610c2e57610c2e6134a7565b604051908082528060200260200182016040528015610c6157816020015b6060815260200190600190039081610c4c5790505b50905060005b8251811015610d4a5760086000848381518110610c8657610c866136a7565b602002602001015181526020019081526020016000208054610ca7906136d6565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd3906136d6565b8015610d205780601f10610cf557610100808354040283529160200191610d20565b820191906000526020600020905b815481529060010190602001808311610d0357829003601f168201915b5050505050828281518110610d3757610d376136a7565b6020908102919091010152600101610c67565b509392505050565b6060610d5e6002612130565b905090565b610d6b611bff565b610d7483610af7565b610db6576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161095a565b610df68282604051610dc9929190613697565b604080519182900390912067ffffffffffffffff861660009081526007602052919091206005019061213d565b610e32578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161095a93929190613772565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610e6e929190613796565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261067190612149565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610f7b906136d6565b80601f0160208091040260200160405190810160405280929190818152602001828054610fa7906136d6565b8015610ff45780601f10610fc957610100808354040283529160200191610ff4565b820191906000526020600020905b815481529060010190602001808311610fd757829003601f168201915b50505050509050919050565b611008611bff565b73ffffffffffffffffffffffffffffffffffffffff8116611055576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110e96005612130565b90506000815167ffffffffffffffff811115611107576111076134a7565b604051908082528060200260200182016040528015611130578160200160208202803683370190505b50905060005b825181101561118c57828181518110611151576111516136a7565b602002602001015182828151811061116b5761116b6136a7565b67ffffffffffffffff90921660209283029190910190910152600101611136565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261067190612149565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906112a5575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112de576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161095a565b6109a38383836121fb565b6112f1611bff565b60005b838110156114de576000858583818110611310576113106136a7565b905060200201602081019061132591906132dc565b905061133c600567ffffffffffffffff831661213d565b61137e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161095a565b67ffffffffffffffff811660009081526007602052604081206113a390600501612130565b905060005b815181101561140f576114068282815181106113c6576113c66136a7565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161213d90919063ffffffff16565b506001016113a8565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906114786004830182612fe3565b600582016000818161148a828261301d565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506114cc915050565b60405180910390a150506001016112f4565b5060005b818110156117f45760008383838181106114fe576114fe6136a7565b905060200281019061151091906137aa565b61151990613876565b905061152a816060015160006122e5565b611539816080015160006122e5565b806040015151600003611578576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516115909060059067ffffffffffffffff16612422565b6115d55780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161095a565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a90910299909316171790941695909517909255909202909117600382015590820151600482019061175890826139ed565b5060005b82602001515181101561179c57611794836000015184602001518381518110611787576117876136a7565b6020026020010151611e08565b60010161175c565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516117e29493929190613b07565b60405180910390a150506001016114e2565b5050505050565b611803611bff565b61180c8161242e565b50565b61182261029360a083016080840161312b565b6118815761183660a082016080830161312b565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161095a565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6118cd60408401602085016132dc565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa15801561193e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119629190613ba0565b15611999576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b16119ac60408301602084016132dc565b6124f2565b6119d16119c460408301602084016132dc565b61033360a0840184613632565b611a16576119e260a0820182613632565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161095a929190613796565b61180c611a2960408301602084016132dc565b8260600135612618565b60008151600003611a6557507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611aa257816040517f953576f700000000000000000000000000000000000000000000000000000000815260040161095a91906130f6565b600082806020019051810190611ab89190613bbd565b905060ff81111561067157826040517f953576f700000000000000000000000000000000000000000000000000000000815260040161095a91906130f6565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611b2d575081610671565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611ba157611b857f000000000000000000000000000000000000000000000000000000000000000083613c05565b611b9090600a613d3e565b611b9a9084613d4d565b9050610671565b611bcb827f0000000000000000000000000000000000000000000000000000000000000000613c05565b611bd690600a613d3e565b611be09084613d88565b9392505050565b60008181526001830160205260408120541515611be0565b60015473ffffffffffffffffffffffffffffffffffffffff163314611c50576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611ca9576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611d3f576000838281518110611cc957611cc96136a7565b60200260200101519050611ce781600261265f90919063ffffffff16565b15611d365760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611cac565b5060005b81518110156109a3576000828281518110611d6057611d606136a7565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611da45750611e00565b611daf600282612681565b15611dfe5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611d43565b8051600003611e43576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611e759060050182612422565b611eaf5782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161095a929190613d9f565b6000818152600860205260409020611ec783826139ed565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610e6e91906130f6565b611f1561029360a083016080840161312b565b611f295761183660a082016080830161312b565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611f7560408401602085016132dc565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611fe6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200a9190613ba0565b15612041576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612059612054606083016040840161312b565b6126a3565b61207161206c60408301602084016132dc565b612722565b61180c61208460408301602084016132dc565b8260600135612870565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b15801561211c57600080fd5b505af11580156117f4573d6000803e3d6000fd5b60606000611be0836128b4565b6000611be0838361290f565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526121d782606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426121bb9190613dc2565b85608001516fffffffffffffffffffffffffffffffff16612a02565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61220483610af7565b612246576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161095a565b6122518260006122e5565b67ffffffffffffffff831660009081526007602052604090206122749083612a2a565b61227f8160006122e5565b67ffffffffffffffff831660009081526007602052604090206122a59060020182612a2a565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516122d893929190613dd5565b60405180910390a1505050565b8151156123b05781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff1610158061233b575060408201516fffffffffffffffffffffffffffffffff16155b1561237457816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161095a9190613e58565b80156123ac576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff161515806123e9575060208201516fffffffffffffffffffffffffffffffff1615155b156123ac57816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161095a9190613e58565b6000611be08383612bcc565b3373ffffffffffffffffffffffffffffffffffffffff82160361247d576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6124fb81610af7565b61253d576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161095a565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156125bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e09190613ba0565b61180c576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161095a565b67ffffffffffffffff821660009081526007602052604090206123ac90600201827f0000000000000000000000000000000000000000000000000000000000000000612c1b565b6000611be08373ffffffffffffffffffffffffffffffffffffffff841661290f565b6000611be08373ffffffffffffffffffffffffffffffffffffffff8416612bcc565b7f00000000000000000000000000000000000000000000000000000000000000001561180c576126d4600282612f9e565b61180c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161095a565b61272b81610af7565b61276d576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161095a565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa1580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190613e94565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461180c576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161095a565b67ffffffffffffffff821660009081526007602052604090206123ac90827f0000000000000000000000000000000000000000000000000000000000000000612c1b565b606081600001805480602002602001604051908101604052809291908181526020018280548015610ff457602002820191906000526020600020905b8154815260200190600101908083116128f05750505050509050919050565b600081815260018301602052604081205480156129f8576000612933600183613dc2565b855490915060009061294790600190613dc2565b90508082146129ac576000866000018281548110612967576129676136a7565b906000526020600020015490508087600001848154811061298a5761298a6136a7565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806129bd576129bd613eb1565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610671565b6000915050610671565b6000612a2185612a128486613d88565b612a1c9087613ee0565b612fcd565b95945050505050565b8154600090612a5390700100000000000000000000000000000000900463ffffffff1642613dc2565b90508015612af55760018301548354612a9b916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612a02565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612b1b916fffffffffffffffffffffffffffffffff9081169116612fcd565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906122d8908490613e58565b6000818152600183016020526040812054612c1357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610671565b506000610671565b825474010000000000000000000000000000000000000000900460ff161580612c42575081155b15612c4c57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612c9290700100000000000000000000000000000000900463ffffffff1642613dc2565b90508015612d525781831115612cd4576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612d0e9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612a02565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612e095773ffffffffffffffffffffffffffffffffffffffff8416612db1576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161095a565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161095a565b84831015612f1c5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612e4d9082613dc2565b612e57878a613dc2565b612e619190613ee0565b612e6b9190613d4d565b905073ffffffffffffffffffffffffffffffffffffffff8616612ec4576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161095a565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161095a565b612f268584613dc2565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611be0565b6000818310612fdc5781611be0565b5090919050565b508054612fef906136d6565b6000825580601f10612fff575050565b601f01602090049060005260206000209081019061180c9190613037565b508054600082559060005260206000209081019061180c91905b5b8082111561304c5760008155600101613038565b5090565b60006020828403121561306257600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611be057600080fd5b6000815180845260005b818110156130b85760208185018101518683018201520161309c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611be06020830184613092565b73ffffffffffffffffffffffffffffffffffffffff8116811461180c57600080fd5b60006020828403121561313d57600080fd5b8135611be081613109565b60006020828403121561315a57600080fd5b813567ffffffffffffffff81111561317157600080fd5b82016101008185031215611be057600080fd5b803567ffffffffffffffff8116811461319c57600080fd5b919050565b6000806000604084860312156131b657600080fd5b6131bf84613184565b9250602084013567ffffffffffffffff808211156131dc57600080fd5b818601915086601f8301126131f057600080fd5b8135818111156131ff57600080fd5b87602082850101111561321157600080fd5b6020830194508093505050509250925092565b60008083601f84011261323657600080fd5b50813567ffffffffffffffff81111561324e57600080fd5b6020830191508360208260051b850101111561326957600080fd5b9250929050565b6000806000806040858703121561328657600080fd5b843567ffffffffffffffff8082111561329e57600080fd5b6132aa88838901613224565b909650945060208701359150808211156132c357600080fd5b506132d087828801613224565b95989497509550505050565b6000602082840312156132ee57600080fd5b611be082613184565b60006020828403121561330957600080fd5b813567ffffffffffffffff81111561332057600080fd5b820160a08185031215611be057600080fd5b60208152600082516040602084015261334e6060840182613092565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612a218282613092565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156133fe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526133ec858351613092565b945092850192908501906001016133b2565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561345957835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613427565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561345957835167ffffffffffffffff1683529284019291840191600101613481565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156134f9576134f96134a7565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613546576135466134a7565b604052919050565b801515811461180c57600080fd5b80356fffffffffffffffffffffffffffffffff8116811461319c57600080fd5b60006060828403121561358e57600080fd5b6040516060810181811067ffffffffffffffff821117156135b1576135b16134a7565b60405290508082356135c28161354e565b81526135d06020840161355c565b60208201526135e16040840161355c565b60408201525092915050565b600080600060e0848603121561360257600080fd5b61360b84613184565b925061361a856020860161357c565b9150613629856080860161357c565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261366757600080fd5b83018035915067ffffffffffffffff82111561368257600080fd5b60200191503681900382131561326957600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c908216806136ea57607f821691505b602082108103613723577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612a21604083018486613729565b602081526000610888602083018486613729565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181126137de57600080fd5b9190910192915050565b600082601f8301126137f957600080fd5b813567ffffffffffffffff811115613813576138136134a7565b61384460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016134ff565b81815284602083860101111561385957600080fd5b816020850160208301376000918101602001919091529392505050565b6000610120823603121561388957600080fd5b6138916134d6565b61389a83613184565b815260208084013567ffffffffffffffff808211156138b857600080fd5b9085019036601f8301126138cb57600080fd5b8135818111156138dd576138dd6134a7565b8060051b6138ec8582016134ff565b918252838101850191858101903684111561390657600080fd5b86860192505b83831015613942578235858111156139245760008081fd5b6139323689838a01016137e8565b835250918601919086019061390c565b808789015250505050604086013592508083111561395f57600080fd5b505061396d368286016137e8565b604083015250613980366060850161357c565b60608201526139923660c0850161357c565b608082015292915050565b601f8211156109a3576000816000526020600020601f850160051c810160208610156139c65750805b601f850160051c820191505b818110156139e5578281556001016139d2565b505050505050565b815167ffffffffffffffff811115613a0757613a076134a7565b613a1b81613a1584546136d6565b8461399d565b602080601f831160018114613a6e5760008415613a385750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556139e5565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613abb57888601518255948401946001909101908401613a9c565b5085821015613af757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613b2b81840187613092565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613b699050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612a21565b600060208284031215613bb257600080fd5b8151611be08161354e565b600060208284031215613bcf57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561067157610671613bd6565b600181815b80851115613c7757817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613c5d57613c5d613bd6565b80851615613c6a57918102915b93841c9390800290613c23565b509250929050565b600082613c8e57506001610671565b81613c9b57506000610671565b8160018114613cb15760028114613cbb57613cd7565b6001915050610671565b60ff841115613ccc57613ccc613bd6565b50506001821b610671565b5060208310610133831016604e8410600b8410161715613cfa575081810a610671565b613d048383613c1e565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613d3657613d36613bd6565b029392505050565b6000611be060ff841683613c7f565b600082613d83577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761067157610671613bd6565b67ffffffffffffffff831681526040602082015260006108886040830184613092565b8181038181111561067157610671613bd6565b67ffffffffffffffff8416815260e08101613e2160208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610888565b6060810161067182848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613ea657600080fd5b8151611be081613109565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561067157610671613bd656fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b5060405162004c5c38038062004c5c833981016040819052620000359162000918565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000206565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e9181019062000a3a565b60015b1562000192578060ff168560ff161462000190576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dc57604080516000815260208101909152620001dc908462000280565b50620001fb935050506001600160a01b038716905030600019620003dd565b505050505062000b84565b336001600160a01b038216036200023057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e051620002a1576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200032c576000838281518110620002c557620002c562000a58565b60209081029190910101519050620002df600282620004c3565b1562000322576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620002a4565b5060005b8151811015620003d857600082828151811062000351576200035162000a58565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200037d5750620003cf565b6200038a600282620004e3565b15620003cd576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000330565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200042f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000455919062000a6e565b62000461919062000a9e565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004bd91869190620004fa16565b50505050565b6000620004da836001600160a01b038416620005cb565b90505b92915050565b6000620004da836001600160a01b038416620006cf565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000549906001600160a01b03851690849062000721565b805190915015620003d857808060200190518101906200056a919062000ab4565b620003d85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000187565b60008181526001830160205260408120548015620006c4576000620005f260018362000adf565b8554909150600090620006089060019062000adf565b9050808214620006745760008660000182815481106200062c576200062c62000a58565b906000526020600020015490508087600001848154811062000652576200065262000a58565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000688576200068862000af5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004dd565b6000915050620004dd565b60008181526001830160205260408120546200071857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004dd565b506000620004dd565b60606200073284846000856200073a565b949350505050565b6060824710156200079d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000187565b600080866001600160a01b03168587604051620007bb919062000b31565b60006040518083038185875af1925050503d8060008114620007fa576040519150601f19603f3d011682016040523d82523d6000602084013e620007ff565b606091505b50909250905062000813878383876200081e565b979650505050505050565b60608315620008925782516000036200088a576001600160a01b0385163b6200088a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000187565b508162000732565b620007328383815115620008a95781518083602001fd5b8060405162461bcd60e51b815260040162000187919062000b4f565b6001600160a01b0381168114620008db57600080fd5b50565b805160ff81168114620008f057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620008f081620008c5565b600080600080600060a086880312156200093157600080fd5b85516200093e81620008c5565b945060206200094f878201620008de565b60408801519095506001600160401b03808211156200096d57600080fd5b818901915089601f8301126200098257600080fd5b815181811115620009975762000997620008f5565b8060051b604051601f19603f83011681018181108582111715620009bf57620009bf620008f5565b60405291825284820192508381018501918c831115620009de57600080fd5b938501935b8285101562000a0757620009f7856200090b565b84529385019392850192620009e3565b80985050505050505062000a1e606087016200090b565b915062000a2e608087016200090b565b90509295509295909350565b60006020828403121562000a4d57600080fd5b620004da82620008de565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a8157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620004dd57620004dd62000a88565b60006020828403121562000ac757600080fd5b8151801515811462000ad857600080fd5b9392505050565b81810381811115620004dd57620004dd62000a88565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000b2857818101518382015260200162000b0e565b50506000910152565b6000825162000b4581846020870162000b0b565b9190910192915050565b602081526000825180602084015262000b7081604085016020870162000b0b565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161402762000c356000396000818161054801528181611d7b01526127cc0152600081816105220152818161189801526120670152600081816102d901528181610ba201528181611a4101528181611afb01528181611b2f01528181611b6201528181611bc701528181611c200152611cc20152600081816102400152818161029501528181610701015281816121ea0152818161276201526129b701526140276000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610520578063e0351e1314610546578063e8a1da171461056c578063f2fde38b1461057f57600080fd5b8063c0d78655146104d2578063c4bffe2b146104e5578063c75eea9c146104fa578063cf7401f31461050d57600080fd5b8063acfecf91116100de578063acfecf911461041f578063af58d59f14610432578063b0f479a1146104a1578063b7946580146104bf57600080fd5b80639a4575b9146103ca578063a42a7b8b146103ea578063a7cd63b71461040a57600080fd5b806354c8a4f31161017157806379ba50971161014b57806379ba50971461037e5780637d54534e146103865780638926f54f146103995780638da5cb5b146103ac57600080fd5b806354c8a4f31461033857806362ddd3c41461034d5780636d3d1a581461036057600080fd5b8063240028e8116101ad578063240028e81461028557806324f65ee7146102d257806339077537146103035780634c5ef0ed1461032557600080fd5b806301ffc9a7146101d4578063181f5a77146101fc57806321df0da71461023e575b600080fd5b6101e76101e2366004613177565b610592565b60405190151581526020015b60405180910390f35b60408051808201909152601f81527f4275726e5769746846726f6d4d696e74546f6b656e506f6f6c20312e352e310060208201525b6040516101f3919061321d565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b6101e7610293366004613252565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101f3565b61031661031136600461326f565b610677565b604051905181526020016101f3565b6101e76103333660046132c8565b610846565b61034b610346366004613397565b610890565b005b61034b61035b3660046132c8565b61090b565b60095473ffffffffffffffffffffffffffffffffffffffff16610260565b61034b6109a8565b61034b610394366004613252565b610a76565b6101e76103a7366004613403565b610af7565b60015473ffffffffffffffffffffffffffffffffffffffff16610260565b6103dd6103d836600461341e565b610b0e565b6040516101f39190613459565b6103fd6103f8366004613403565b610be7565b6040516101f391906134b0565b610412610d52565b6040516101f39190613532565b61034b61042d3660046132c8565b610d63565b610445610440366004613403565b610e7b565b6040516101f3919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610260565b6102316104cd366004613403565b610f50565b61034b6104e0366004613252565b611000565b6104ed6110db565b6040516101f3919061358c565b610445610508366004613403565b611193565b61034b61051b366004613714565b611265565b7f0000000000000000000000000000000000000000000000000000000000000000610260565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b61034b61057a366004613397565b6112e9565b61034b61058d366004613252565b6117fb565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062557507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60408051602081019091526000815261068f8261180f565b60006106e860608401356106e36106a960c0870187613759565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3392505050565b611af7565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107366060860160408701613252565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107a357600080fd5b505af11580156107b7573d6000803e3d6000fd5b506107cc925050506060840160408501613252565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161082a91815260200190565b60405180910390a3604080516020810190915290815292915050565b6000610888838360405161085b9291906137be565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611d0b565b949350505050565b610898611d26565b61090584848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611d7992505050565b50505050565b610913611d26565b61091c83610af7565b610963576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109a38383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f2f92505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109f9576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a7e611d26565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610671600567ffffffffffffffff8416611d0b565b6040805180820190915260608082526020820152610b2b82612029565b610b3882606001356121b5565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b928460200160208101906104cd9190613403565b8152602001610bdf6040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610c1090600501612257565b90506000815167ffffffffffffffff811115610c2e57610c2e6135ce565b604051908082528060200260200182016040528015610c6157816020015b6060815260200190600190039081610c4c5790505b50905060005b8251811015610d4a5760086000848381518110610c8657610c866137ce565b602002602001015181526020019081526020016000208054610ca7906137fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd3906137fd565b8015610d205780601f10610cf557610100808354040283529160200191610d20565b820191906000526020600020905b815481529060010190602001808311610d0357829003601f168201915b5050505050828281518110610d3757610d376137ce565b6020908102919091010152600101610c67565b509392505050565b6060610d5e6002612257565b905090565b610d6b611d26565b610d7483610af7565b610db6576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161095a565b610df68282604051610dc99291906137be565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190612264565b610e32578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161095a93929190613899565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610e6e9291906138bd565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261067190612270565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610f7b906137fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610fa7906137fd565b8015610ff45780601f10610fc957610100808354040283529160200191610ff4565b820191906000526020600020905b815481529060010190602001808311610fd757829003601f168201915b50505050509050919050565b611008611d26565b73ffffffffffffffffffffffffffffffffffffffff8116611055576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110e96005612257565b90506000815167ffffffffffffffff811115611107576111076135ce565b604051908082528060200260200182016040528015611130578160200160208202803683370190505b50905060005b825181101561118c57828181518110611151576111516137ce565b602002602001015182828151811061116b5761116b6137ce565b67ffffffffffffffff90921660209283029190910190910152600101611136565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261067190612270565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906112a5575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112de576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161095a565b6109a3838383612322565b6112f1611d26565b60005b838110156114de576000858583818110611310576113106137ce565b90506020020160208101906113259190613403565b905061133c600567ffffffffffffffff8316612264565b61137e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161095a565b67ffffffffffffffff811660009081526007602052604081206113a390600501612257565b905060005b815181101561140f576114068282815181106113c6576113c66137ce565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161226490919063ffffffff16565b506001016113a8565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611478600483018261310a565b600582016000818161148a8282613144565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506114cc915050565b60405180910390a150506001016112f4565b5060005b818110156117f45760008383838181106114fe576114fe6137ce565b905060200281019061151091906138d1565b6115199061399d565b905061152a8160600151600061240c565b6115398160800151600061240c565b806040015151600003611578576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516115909060059067ffffffffffffffff16612549565b6115d55780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161095a565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a9091029990931617179094169590951790925590920290911760038201559082015160048201906117589082613b14565b5060005b82602001515181101561179c57611794836000015184602001518381518110611787576117876137ce565b6020026020010151611f2f565b60010161175c565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516117e29493929190613c2e565b60405180910390a150506001016114e2565b5050505050565b611803611d26565b61180c81612555565b50565b61182261029360a0830160808401613252565b6118815761183660a0820160808301613252565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161095a565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6118cd6040840160208501613403565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa15801561193e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119629190613cc7565b15611999576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b16119ac6040830160208401613403565b612619565b6119d16119c46040830160208401613403565b61033360a0840184613759565b611a16576119e260a0820182613759565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161095a9291906138bd565b61180c611a296040830160208401613403565b826060013561273f565b60008151600003611a6557507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611aa257816040517f953576f700000000000000000000000000000000000000000000000000000000815260040161095a919061321d565b600082806020019051810190611ab89190613ce4565b905060ff81111561067157826040517f953576f700000000000000000000000000000000000000000000000000000000815260040161095a919061321d565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611b2d575081610671565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611c18576000611b877f000000000000000000000000000000000000000000000000000000000000000084613d2c565b9050604d8160ff161115611bfb576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161095a565b611c0681600a613e65565b611c109085613e74565b915050610671565b6000611c44837f0000000000000000000000000000000000000000000000000000000000000000613d2c565b9050604d8160ff161180611c8b5750611c5e81600a613e65565b611c88907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613e74565b84115b15611cf6576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161095a565b611d0181600a613e65565b6108889085613eaf565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d77576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611dd0576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611e66576000838281518110611df057611df06137ce565b60200260200101519050611e0e81600261278690919063ffffffff16565b15611e5d5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611dd3565b5060005b81518110156109a3576000828281518110611e8757611e876137ce565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ecb5750611f27565b611ed66002826127a8565b15611f255760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611e6a565b8051600003611f6a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611f9c9060050182612549565b611fd65782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161095a929190613ec6565b6000818152600860205260409020611fee8382613b14565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610e6e919061321d565b61203c61029360a0830160808401613252565b6120505761183660a0820160808301613252565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb61209c6040840160208501613403565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa15801561210d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121319190613cc7565b15612168576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61218061217b6060830160408401613252565b6127ca565b6121986121936040830160208401613403565b612849565b61180c6121ab6040830160208401613403565b8260600135612997565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b15801561224357600080fd5b505af11580156117f4573d6000803e3d6000fd5b60606000611d1f836129db565b6000611d1f8383612a36565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526122fe82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426122e29190613ee9565b85608001516fffffffffffffffffffffffffffffffff16612b29565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61232b83610af7565b61236d576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161095a565b61237882600061240c565b67ffffffffffffffff8316600090815260076020526040902061239b9083612b51565b6123a681600061240c565b67ffffffffffffffff831660009081526007602052604090206123cc9060020182612b51565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516123ff93929190613efc565b60405180910390a1505050565b8151156124d75781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612462575060408201516fffffffffffffffffffffffffffffffff16155b1561249b57816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161095a9190613f7f565b80156124d3576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612510575060208201516fffffffffffffffffffffffffffffffff1615155b156124d357816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161095a9190613f7f565b6000611d1f8383612cf3565b3373ffffffffffffffffffffffffffffffffffffffff8216036125a4576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61262281610af7565b612664576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161095a565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156126e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127079190613cc7565b61180c576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161095a565b67ffffffffffffffff821660009081526007602052604090206124d390600201827f0000000000000000000000000000000000000000000000000000000000000000612d42565b6000611d1f8373ffffffffffffffffffffffffffffffffffffffff8416612a36565b6000611d1f8373ffffffffffffffffffffffffffffffffffffffff8416612cf3565b7f00000000000000000000000000000000000000000000000000000000000000001561180c576127fb6002826130c5565b61180c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161095a565b61285281610af7565b612894576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161095a565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561290d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129319190613fbb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461180c576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161095a565b67ffffffffffffffff821660009081526007602052604090206124d390827f0000000000000000000000000000000000000000000000000000000000000000612d42565b606081600001805480602002602001604051908101604052809291908181526020018280548015610ff457602002820191906000526020600020905b815481526020019060010190808311612a175750505050509050919050565b60008181526001830160205260408120548015612b1f576000612a5a600183613ee9565b8554909150600090612a6e90600190613ee9565b9050808214612ad3576000866000018281548110612a8e57612a8e6137ce565b9060005260206000200154905080876000018481548110612ab157612ab16137ce565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ae457612ae4613fd8565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610671565b6000915050610671565b6000612b4885612b398486613eaf565b612b439087614007565b6130f4565b95945050505050565b8154600090612b7a90700100000000000000000000000000000000900463ffffffff1642613ee9565b90508015612c1c5760018301548354612bc2916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612b29565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612c42916fffffffffffffffffffffffffffffffff90811691166130f4565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906123ff908490613f7f565b6000818152600183016020526040812054612d3a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610671565b506000610671565b825474010000000000000000000000000000000000000000900460ff161580612d69575081155b15612d7357505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612db990700100000000000000000000000000000000900463ffffffff1642613ee9565b90508015612e795781831115612dfb576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612e359083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612b29565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612f305773ffffffffffffffffffffffffffffffffffffffff8416612ed8576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161095a565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161095a565b848310156130435760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612f749082613ee9565b612f7e878a613ee9565b612f889190614007565b612f929190613e74565b905073ffffffffffffffffffffffffffffffffffffffff8616612feb576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161095a565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161095a565b61304d8584613ee9565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611d1f565b60008183106131035781611d1f565b5090919050565b508054613116906137fd565b6000825580601f10613126575050565b601f01602090049060005260206000209081019061180c919061315e565b508054600082559060005260206000209081019061180c91905b5b80821115613173576000815560010161315f565b5090565b60006020828403121561318957600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611d1f57600080fd5b6000815180845260005b818110156131df576020818501810151868301820152016131c3565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611d1f60208301846131b9565b73ffffffffffffffffffffffffffffffffffffffff8116811461180c57600080fd5b60006020828403121561326457600080fd5b8135611d1f81613230565b60006020828403121561328157600080fd5b813567ffffffffffffffff81111561329857600080fd5b82016101008185031215611d1f57600080fd5b803567ffffffffffffffff811681146132c357600080fd5b919050565b6000806000604084860312156132dd57600080fd5b6132e6846132ab565b9250602084013567ffffffffffffffff8082111561330357600080fd5b818601915086601f83011261331757600080fd5b81358181111561332657600080fd5b87602082850101111561333857600080fd5b6020830194508093505050509250925092565b60008083601f84011261335d57600080fd5b50813567ffffffffffffffff81111561337557600080fd5b6020830191508360208260051b850101111561339057600080fd5b9250929050565b600080600080604085870312156133ad57600080fd5b843567ffffffffffffffff808211156133c557600080fd5b6133d18883890161334b565b909650945060208701359150808211156133ea57600080fd5b506133f78782880161334b565b95989497509550505050565b60006020828403121561341557600080fd5b611d1f826132ab565b60006020828403121561343057600080fd5b813567ffffffffffffffff81111561344757600080fd5b820160a08185031215611d1f57600080fd5b60208152600082516040602084015261347560608401826131b9565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612b4882826131b9565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613525577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526135138583516131b9565b945092850192908501906001016134d9565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358057835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161354e565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358057835167ffffffffffffffff16835292840192918401916001016135a8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613620576136206135ce565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561366d5761366d6135ce565b604052919050565b801515811461180c57600080fd5b80356fffffffffffffffffffffffffffffffff811681146132c357600080fd5b6000606082840312156136b557600080fd5b6040516060810181811067ffffffffffffffff821117156136d8576136d86135ce565b60405290508082356136e981613675565b81526136f760208401613683565b602082015261370860408401613683565b60408201525092915050565b600080600060e0848603121561372957600080fd5b613732846132ab565b925061374185602086016136a3565b915061375085608086016136a3565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261378e57600080fd5b83018035915067ffffffffffffffff8211156137a957600080fd5b60200191503681900382131561339057600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061381157607f821691505b60208210810361384a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612b48604083018486613850565b602081526000610888602083018486613850565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261390557600080fd5b9190910192915050565b600082601f83011261392057600080fd5b813567ffffffffffffffff81111561393a5761393a6135ce565b61396b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613626565b81815284602083860101111561398057600080fd5b816020850160208301376000918101602001919091529392505050565b600061012082360312156139b057600080fd5b6139b86135fd565b6139c1836132ab565b815260208084013567ffffffffffffffff808211156139df57600080fd5b9085019036601f8301126139f257600080fd5b813581811115613a0457613a046135ce565b8060051b613a13858201613626565b9182528381018501918581019036841115613a2d57600080fd5b86860192505b83831015613a6957823585811115613a4b5760008081fd5b613a593689838a010161390f565b8352509186019190860190613a33565b8087890152505050506040860135925080831115613a8657600080fd5b5050613a943682860161390f565b604083015250613aa736606085016136a3565b6060820152613ab93660c085016136a3565b608082015292915050565b601f8211156109a3576000816000526020600020601f850160051c81016020861015613aed5750805b601f850160051c820191505b81811015613b0c57828155600101613af9565b505050505050565b815167ffffffffffffffff811115613b2e57613b2e6135ce565b613b4281613b3c84546137fd565b84613ac4565b602080601f831160018114613b955760008415613b5f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b0c565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613be257888601518255948401946001909101908401613bc3565b5085821015613c1e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613c52818401876131b9565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613c909050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612b48565b600060208284031215613cd957600080fd5b8151611d1f81613675565b600060208284031215613cf657600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561067157610671613cfd565b600181815b80851115613d9e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613d8457613d84613cfd565b80851615613d9157918102915b93841c9390800290613d4a565b509250929050565b600082613db557506001610671565b81613dc257506000610671565b8160018114613dd85760028114613de257613dfe565b6001915050610671565b60ff841115613df357613df3613cfd565b50506001821b610671565b5060208310610133831016604e8410600b8410161715613e21575081810a610671565b613e2b8383613d45565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613e5d57613e5d613cfd565b029392505050565b6000611d1f60ff841683613da6565b600082613eaa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761067157610671613cfd565b67ffffffffffffffff8316815260406020820152600061088860408301846131b9565b8181038181111561067157610671613cfd565b67ffffffffffffffff8416815260e08101613f4860208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610888565b6060810161067182848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613fcd57600080fd5b8151611d1f81613230565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561067157610671613cfd56fea164736f6c6343000818000a", } var BurnWithFromMintTokenPoolABI = BurnWithFromMintTokenPoolMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go index 168d31806b8..7397594d78d 100644 --- a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go +++ b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go @@ -100,8 +100,8 @@ type OffRampSourceChainConfig struct { } var CCIPReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPMessageSent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"getInboundNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"testNonce\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"setInboundNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506118e3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063c1a5a35511610076578063c92236251161005b578063c92236251461017c578063e83eabba1461018f578063e9d68a8e146101a257600080fd5b8063c1a5a35514610114578063c7c1cba11461016957600080fd5b80634bf78697146100a85780639041be3d146100bd57806393df2867146100ee578063bfc9b78914610101575b600080fd5b6100bb6100b63660046109d1565b6101c2565b005b6100d06100cb366004610b0c565b61021b565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6100bb6100fc366004610b77565b61024b565b6100bb61010f366004610e25565b6102c6565b6100bb610122366004610fb0565b67ffffffffffffffff918216600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001691909216179055565b6100bb610177366004610fe3565b610308565b6100d061018a366004611075565b610365565b6100bb61019d3660046110c8565b6103b1565b6101b56101b0366004610b0c565b61049b565b6040516100e591906111e8565b80600001516060015167ffffffffffffffff168267ffffffffffffffff167f192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f328360405161020f919061132e565b60405180910390a35050565b67ffffffffffffffff80821660009081526001602081905260408220549192610245921690611486565b92915050565b67ffffffffffffffff841660009081526002602052604090819020905184919061027890859085906114d5565b908152604051908190036020019020805467ffffffffffffffff929092167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905550505050565b602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e4926102fd9290916115d9565b60405180910390a150565b848667ffffffffffffffff168867ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8787878760405161035494939291906116b1565b60405180910390a450505050505050565b67ffffffffffffffff8316600090815260026020526040808220905161038e90859085906114d5565b9081526040519081900360200190205467ffffffffffffffff1690509392505050565b67ffffffffffffffff808316600090815260208181526040918290208451815492860151938601519094167501000000000000000000000000000000000000000000027fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff93151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090931673ffffffffffffffffffffffffffffffffffffffff9095169490941791909117919091169190911781556060820151829190600182019061049490826117bc565b5050505050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff87811684528383529286902086519485018752805473ffffffffffffffffffffffffffffffffffffffff8116865274010000000000000000000000000000000000000000810460ff16151593860193909352750100000000000000000000000000000000000000000090920490921694830194909452600184018054939492939184019161055790611718565b80601f016020809104026020016040519081016040528092919081815260200182805461058390611718565b80156105d05780601f106105a5576101008083540402835291602001916105d0565b820191906000526020600020905b8154815290600101906020018083116105b357829003601f168201915b5050505050815250509050919050565b803567ffffffffffffffff811681146105f857600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561064f5761064f6105fd565b60405290565b604051610120810167ffffffffffffffff8111828210171561064f5761064f6105fd565b6040805190810167ffffffffffffffff8111828210171561064f5761064f6105fd565b6040516060810167ffffffffffffffff8111828210171561064f5761064f6105fd565b6040516080810167ffffffffffffffff8111828210171561064f5761064f6105fd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610729576107296105fd565b604052919050565b600060a0828403121561074357600080fd5b61074b61062c565b90508135815261075d602083016105e0565b602082015261076e604083016105e0565b604082015261077f606083016105e0565b6060820152610790608083016105e0565b608082015292915050565b73ffffffffffffffffffffffffffffffffffffffff811681146107bd57600080fd5b50565b80356105f88161079b565b600082601f8301126107dc57600080fd5b813567ffffffffffffffff8111156107f6576107f66105fd565b61082760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016106e2565b81815284602083860101111561083c57600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115610873576108736105fd565b5060051b60200190565b600082601f83011261088e57600080fd5b813560206108a361089e83610859565b6106e2565b82815260059290921b840181019181810190868411156108c257600080fd5b8286015b848110156109c657803567ffffffffffffffff808211156108e75760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156109205760008081fd5b61092861062c565b6109338885016107c0565b8152604080850135848111156109495760008081fd5b6109578e8b838901016107cb565b8a84015250606080860135858111156109705760008081fd5b61097e8f8c838a01016107cb565b838501525060809150818601358184015250828501359250838311156109a45760008081fd5b6109b28d8a858801016107cb565b9082015286525050509183019183016108c6565b509695505050505050565b600080604083850312156109e457600080fd5b6109ed836105e0565b9150602083013567ffffffffffffffff80821115610a0a57600080fd5b908401906101a08287031215610a1f57600080fd5b610a27610655565b610a318784610731565b8152610a3f60a084016107c0565b602082015260c083013582811115610a5657600080fd5b610a62888286016107cb565b60408301525060e083013582811115610a7a57600080fd5b610a86888286016107cb565b6060830152506101008084013583811115610aa057600080fd5b610aac898287016107cb565b608084015250610abf61012085016107c0565b60a083015261014084013560c083015261016084013560e083015261018084013583811115610aed57600080fd5b610af98982870161087d565b8284015250508093505050509250929050565b600060208284031215610b1e57600080fd5b610b27826105e0565b9392505050565b60008083601f840112610b4057600080fd5b50813567ffffffffffffffff811115610b5857600080fd5b602083019150836020828501011115610b7057600080fd5b9250929050565b60008060008060608587031215610b8d57600080fd5b610b96856105e0565b9350610ba4602086016105e0565b9250604085013567ffffffffffffffff811115610bc057600080fd5b610bcc87828801610b2e565b95989497509550505050565b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146105f857600080fd5b600082601f830112610c1557600080fd5b81356020610c2561089e83610859565b82815260069290921b84018101918181019086841115610c4457600080fd5b8286015b848110156109c65760408189031215610c615760008081fd5b610c69610679565b610c72826105e0565b8152610c7f858301610bd8565b81860152835291830191604001610c48565b600082601f830112610ca257600080fd5b81356020610cb261089e83610859565b82815260059290921b84018101918181019086841115610cd157600080fd5b8286015b848110156109c657803567ffffffffffffffff80821115610cf65760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610d2f5760008081fd5b610d3761062c565b610d428885016105e0565b815260408085013584811115610d585760008081fd5b610d668e8b838901016107cb565b8a8401525060609350610d7a8486016105e0565b908201526080610d8b8582016105e0565b93820193909352920135908201528352918301918301610cd5565b600082601f830112610db757600080fd5b81356020610dc761089e83610859565b82815260069290921b84018101918181019086841115610de657600080fd5b8286015b848110156109c65760408189031215610e035760008081fd5b610e0b610679565b813581528482013585820152835291830191604001610dea565b60006020808385031215610e3857600080fd5b823567ffffffffffffffff80821115610e5057600080fd5b9084019060608287031215610e6457600080fd5b610e6c61069c565b823582811115610e7b57600080fd5b83016040818903811315610e8e57600080fd5b610e96610679565b823585811115610ea557600080fd5b8301601f81018b13610eb657600080fd5b8035610ec461089e82610859565b81815260069190911b8201890190898101908d831115610ee357600080fd5b928a01925b82841015610f335785848f031215610f005760008081fd5b610f08610679565b8435610f138161079b565b8152610f20858d01610bd8565b818d0152825292850192908a0190610ee8565b845250505082870135915084821115610f4b57600080fd5b610f578a838501610c04565b81880152835250508284013582811115610f7057600080fd5b610f7c88828601610c91565b85830152506040830135935081841115610f9557600080fd5b610fa187858501610da6565b60408201529695505050505050565b60008060408385031215610fc357600080fd5b610fcc836105e0565b9150610fda602084016105e0565b90509250929050565b600080600080600080600060e0888a031215610ffe57600080fd5b611007886105e0565b9650611015602089016105e0565b9550604088013594506060880135935060808801356004811061103757600080fd5b925060a088013567ffffffffffffffff81111561105357600080fd5b61105f8a828b016107cb565b92505060c0880135905092959891949750929550565b60008060006040848603121561108a57600080fd5b611093846105e0565b9250602084013567ffffffffffffffff8111156110af57600080fd5b6110bb86828701610b2e565b9497909650939450505050565b600080604083850312156110db57600080fd5b6110e4836105e0565b9150602083013567ffffffffffffffff8082111561110157600080fd5b908401906080828703121561111557600080fd5b61111d6106bf565b82356111288161079b565b81526020830135801515811461113d57600080fd5b602082015261114e604084016105e0565b604082015260608301358281111561116557600080fd5b611171888286016107cb565b6060830152508093505050509250929050565b6000815180845260005b818110156111aa5760208185018101518683018201520161118e565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260208201511515604082015267ffffffffffffffff60408301511660608201526000606083015160808084015261124360a0840182611184565b949350505050565b600082825180855260208086019550808260051b84010181860160005b84811015611321577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a073ffffffffffffffffffffffffffffffffffffffff82511685528582015181878701526112ca82870182611184565b915050604080830151868303828801526112e48382611184565b9250505060608083015181870152506080808301519250858203818701525061130d8183611184565b9a86019a9450505090830190600101611268565b5090979650505050505050565b6020815261137f60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208301516113a860c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101a08060e08501526113c56101c0850183611184565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008187860301818801526114038584611184565b94506080880151925081878603016101208801526114218584611184565b945060a0880151925061144d61014088018473ffffffffffffffffffffffffffffffffffffffff169052565b60c088015161016088015260e088015161018088015287015186850390910183870152905061147c838261124b565b9695505050505050565b67ffffffffffffffff8181168382160190808211156114ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5092915050565b8183823760009101908152919050565b805160408084528151848201819052600092602091908201906060870190855b8181101561155e578351805173ffffffffffffffffffffffffffffffffffffffff1684528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858401529284019291850191600101611505565b50508583015187820388850152805180835290840192506000918401905b808310156115cd578351805167ffffffffffffffff1683528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168583015292840192600192909201919085019061157c565b50979650505050505050565b60006040808301604084528086518083526060925060608601915060608160051b8701016020808a0160005b84811015611691577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08a8503018652815160a067ffffffffffffffff80835116875285830151828789015261165c83890182611184565b848d01518316898e01528b8501519092168b890152506080928301519290960191909152509482019490820190600101611605565b5050878203908801526116a481896114e5565b9998505050505050505050565b8481526000600485106116ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b846020830152608060408301526117076080830185611184565b905082606083015295945050505050565b600181811c9082168061172c57607f821691505b602082108103611765577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156117b7576000816000526020600020601f850160051c810160208610156117945750805b601f850160051c820191505b818110156117b3578281556001016117a0565b5050505b505050565b815167ffffffffffffffff8111156117d6576117d66105fd565b6117ea816117e48454611718565b8461176b565b602080601f83116001811461183d57600084156118075750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556117b3565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561188a5788860151825594840194600190910190840161186b565b50858210156118c657878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPMessageSent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"getInboundNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"testNonce\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"setInboundNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"seqNr\",\"type\":\"uint64\"}],\"name\":\"setLatestPriceSequenceNumber\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b50611960806100206000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c8063bfc9b78911610081578063c92236251161005b578063c9223625146101f9578063e83eabba1461020c578063e9d68a8e1461021f57600080fd5b8063bfc9b7891461017e578063c1a5a35514610191578063c7c1cba1146101e657600080fd5b806369600bca116100b257806369600bca1461010f5780639041be3d1461015857806393df28671461016b57600080fd5b80633f4b04aa146100ce5780634bf78697146100fa575b600080fd5b60035467ffffffffffffffff165b60405167ffffffffffffffff90911681526020015b60405180910390f35b61010d610108366004610a4e565b61023f565b005b61010d61011d366004610b89565b600380547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b6100dc610166366004610b89565b610298565b61010d610179366004610bf4565b6102c8565b61010d61018c366004610ea2565b610343565b61010d61019f36600461102d565b67ffffffffffffffff918216600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001691909216179055565b61010d6101f4366004611060565b610385565b6100dc6102073660046110f2565b6103e2565b61010d61021a366004611145565b61042e565b61023261022d366004610b89565b610518565b6040516100f19190611265565b80600001516060015167ffffffffffffffff168267ffffffffffffffff167f192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f328360405161028c91906113ab565b60405180910390a35050565b67ffffffffffffffff808216600090815260016020819052604082205491926102c2921690611503565b92915050565b67ffffffffffffffff84166000908152600260205260409081902090518491906102f59085908590611552565b908152604051908190036020019020805467ffffffffffffffff929092167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905550505050565b602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261037a929091611656565b60405180910390a150565b848667ffffffffffffffff168867ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b878787876040516103d1949392919061172e565b60405180910390a450505050505050565b67ffffffffffffffff8316600090815260026020526040808220905161040b9085908590611552565b9081526040519081900360200190205467ffffffffffffffff1690509392505050565b67ffffffffffffffff808316600090815260208181526040918290208451815492860151938601519094167501000000000000000000000000000000000000000000027fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff93151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090931673ffffffffffffffffffffffffffffffffffffffff909516949094179190911791909116919091178155606082015182919060018201906105119082611839565b5050505050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff87811684528383529286902086519485018752805473ffffffffffffffffffffffffffffffffffffffff8116865274010000000000000000000000000000000000000000810460ff1615159386019390935275010000000000000000000000000000000000000000009092049092169483019490945260018401805493949293918401916105d490611795565b80601f016020809104026020016040519081016040528092919081815260200182805461060090611795565b801561064d5780601f106106225761010080835404028352916020019161064d565b820191906000526020600020905b81548152906001019060200180831161063057829003601f168201915b5050505050815250509050919050565b803567ffffffffffffffff8116811461067557600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156106cc576106cc61067a565b60405290565b604051610120810167ffffffffffffffff811182821017156106cc576106cc61067a565b6040805190810167ffffffffffffffff811182821017156106cc576106cc61067a565b6040516060810167ffffffffffffffff811182821017156106cc576106cc61067a565b6040516080810167ffffffffffffffff811182821017156106cc576106cc61067a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156107a6576107a661067a565b604052919050565b600060a082840312156107c057600080fd5b6107c86106a9565b9050813581526107da6020830161065d565b60208201526107eb6040830161065d565b60408201526107fc6060830161065d565b606082015261080d6080830161065d565b608082015292915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461083a57600080fd5b50565b803561067581610818565b600082601f83011261085957600080fd5b813567ffffffffffffffff8111156108735761087361067a565b6108a460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161075f565b8181528460208386010111156108b957600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff8211156108f0576108f061067a565b5060051b60200190565b600082601f83011261090b57600080fd5b8135602061092061091b836108d6565b61075f565b82815260059290921b8401810191818101908684111561093f57600080fd5b8286015b84811015610a4357803567ffffffffffffffff808211156109645760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d0301121561099d5760008081fd5b6109a56106a9565b6109b088850161083d565b8152604080850135848111156109c65760008081fd5b6109d48e8b83890101610848565b8a84015250606080860135858111156109ed5760008081fd5b6109fb8f8c838a0101610848565b83850152506080915081860135818401525082850135925083831115610a215760008081fd5b610a2f8d8a85880101610848565b908201528652505050918301918301610943565b509695505050505050565b60008060408385031215610a6157600080fd5b610a6a8361065d565b9150602083013567ffffffffffffffff80821115610a8757600080fd5b908401906101a08287031215610a9c57600080fd5b610aa46106d2565b610aae87846107ae565b8152610abc60a0840161083d565b602082015260c083013582811115610ad357600080fd5b610adf88828601610848565b60408301525060e083013582811115610af757600080fd5b610b0388828601610848565b6060830152506101008084013583811115610b1d57600080fd5b610b2989828701610848565b608084015250610b3c610120850161083d565b60a083015261014084013560c083015261016084013560e083015261018084013583811115610b6a57600080fd5b610b76898287016108fa565b8284015250508093505050509250929050565b600060208284031215610b9b57600080fd5b610ba48261065d565b9392505050565b60008083601f840112610bbd57600080fd5b50813567ffffffffffffffff811115610bd557600080fd5b602083019150836020828501011115610bed57600080fd5b9250929050565b60008060008060608587031215610c0a57600080fd5b610c138561065d565b9350610c216020860161065d565b9250604085013567ffffffffffffffff811115610c3d57600080fd5b610c4987828801610bab565b95989497509550505050565b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461067557600080fd5b600082601f830112610c9257600080fd5b81356020610ca261091b836108d6565b82815260069290921b84018101918181019086841115610cc157600080fd5b8286015b84811015610a435760408189031215610cde5760008081fd5b610ce66106f6565b610cef8261065d565b8152610cfc858301610c55565b81860152835291830191604001610cc5565b600082601f830112610d1f57600080fd5b81356020610d2f61091b836108d6565b82815260059290921b84018101918181019086841115610d4e57600080fd5b8286015b84811015610a4357803567ffffffffffffffff80821115610d735760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610dac5760008081fd5b610db46106a9565b610dbf88850161065d565b815260408085013584811115610dd55760008081fd5b610de38e8b83890101610848565b8a8401525060609350610df784860161065d565b908201526080610e0885820161065d565b93820193909352920135908201528352918301918301610d52565b600082601f830112610e3457600080fd5b81356020610e4461091b836108d6565b82815260069290921b84018101918181019086841115610e6357600080fd5b8286015b84811015610a435760408189031215610e805760008081fd5b610e886106f6565b813581528482013585820152835291830191604001610e67565b60006020808385031215610eb557600080fd5b823567ffffffffffffffff80821115610ecd57600080fd5b9084019060608287031215610ee157600080fd5b610ee9610719565b823582811115610ef857600080fd5b83016040818903811315610f0b57600080fd5b610f136106f6565b823585811115610f2257600080fd5b8301601f81018b13610f3357600080fd5b8035610f4161091b826108d6565b81815260069190911b8201890190898101908d831115610f6057600080fd5b928a01925b82841015610fb05785848f031215610f7d5760008081fd5b610f856106f6565b8435610f9081610818565b8152610f9d858d01610c55565b818d0152825292850192908a0190610f65565b845250505082870135915084821115610fc857600080fd5b610fd48a838501610c81565b81880152835250508284013582811115610fed57600080fd5b610ff988828601610d0e565b8583015250604083013593508184111561101257600080fd5b61101e87858501610e23565b60408201529695505050505050565b6000806040838503121561104057600080fd5b6110498361065d565b91506110576020840161065d565b90509250929050565b600080600080600080600060e0888a03121561107b57600080fd5b6110848861065d565b96506110926020890161065d565b955060408801359450606088013593506080880135600481106110b457600080fd5b925060a088013567ffffffffffffffff8111156110d057600080fd5b6110dc8a828b01610848565b92505060c0880135905092959891949750929550565b60008060006040848603121561110757600080fd5b6111108461065d565b9250602084013567ffffffffffffffff81111561112c57600080fd5b61113886828701610bab565b9497909650939450505050565b6000806040838503121561115857600080fd5b6111618361065d565b9150602083013567ffffffffffffffff8082111561117e57600080fd5b908401906080828703121561119257600080fd5b61119a61073c565b82356111a581610818565b8152602083013580151581146111ba57600080fd5b60208201526111cb6040840161065d565b60408201526060830135828111156111e257600080fd5b6111ee88828601610848565b6060830152508093505050509250929050565b6000815180845260005b818110156112275760208185018101518683018201520161120b565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526112c060a0840182611201565b949350505050565b600082825180855260208086019550808260051b84010181860160005b8481101561139e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a073ffffffffffffffffffffffffffffffffffffffff825116855285820151818787015261134782870182611201565b915050604080830151868303828801526113618382611201565b9250505060608083015181870152506080808301519250858203818701525061138a8183611201565b9a86019a94505050908301906001016112e5565b5090979650505050505050565b602081526113fc60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161142560c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101a08060e08501526114426101c0850183611201565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008187860301818801526114808584611201565b945060808801519250818786030161012088015261149e8584611201565b945060a088015192506114ca61014088018473ffffffffffffffffffffffffffffffffffffffff169052565b60c088015161016088015260e08801516101808801528701518685039091018387015290506114f983826112c8565b9695505050505050565b67ffffffffffffffff81811683821601908082111561154b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5092915050565b8183823760009101908152919050565b805160408084528151848201819052600092602091908201906060870190855b818110156115db578351805173ffffffffffffffffffffffffffffffffffffffff1684528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858401529284019291850191600101611582565b50508583015187820388850152805180835290840192506000918401905b8083101561164a578351805167ffffffffffffffff1683528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858301529284019260019290920191908501906115f9565b50979650505050505050565b60006040808301604084528086518083526060925060608601915060608160051b8701016020808a0160005b8481101561170e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08a8503018652815160a067ffffffffffffffff8083511687528583015182878901526116d983890182611201565b848d01518316898e01528b8501519092168b890152506080928301519290960191909152509482019490820190600101611682565b5050878203908801526117218189611562565b9998505050505050505050565b84815260006004851061176a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b846020830152608060408301526117846080830185611201565b905082606083015295945050505050565b600181811c908216806117a957607f821691505b6020821081036117e2577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115611834576000816000526020600020601f850160051c810160208610156118115750805b601f850160051c820191505b818110156118305782815560010161181d565b5050505b505050565b815167ffffffffffffffff8111156118535761185361067a565b611867816118618454611795565b846117e8565b602080601f8311600181146118ba57600084156118845750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611830565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611907578886015182559484019460019091019084016118e8565b508582101561194357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", } var CCIPReaderTesterABI = CCIPReaderTesterMetaData.ABI @@ -284,6 +284,28 @@ func (_CCIPReaderTester *CCIPReaderTesterCallerSession) GetInboundNonce(sourceCh return _CCIPReaderTester.Contract.GetInboundNonce(&_CCIPReaderTester.CallOpts, sourceChainSelector, sender) } +func (_CCIPReaderTester *CCIPReaderTesterCaller) GetLatestPriceSequenceNumber(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _CCIPReaderTester.contract.Call(opts, &out, "getLatestPriceSequenceNumber") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) GetLatestPriceSequenceNumber() (uint64, error) { + return _CCIPReaderTester.Contract.GetLatestPriceSequenceNumber(&_CCIPReaderTester.CallOpts) +} + +func (_CCIPReaderTester *CCIPReaderTesterCallerSession) GetLatestPriceSequenceNumber() (uint64, error) { + return _CCIPReaderTester.Contract.GetLatestPriceSequenceNumber(&_CCIPReaderTester.CallOpts) +} + func (_CCIPReaderTester *CCIPReaderTesterCaller) GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (OffRampSourceChainConfig, error) { var out []interface{} err := _CCIPReaderTester.contract.Call(opts, &out, "getSourceChainConfig", sourceChainSelector) @@ -366,6 +388,18 @@ func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) SetInboundNonce(sour return _CCIPReaderTester.Contract.SetInboundNonce(&_CCIPReaderTester.TransactOpts, sourceChainSelector, testNonce, sender) } +func (_CCIPReaderTester *CCIPReaderTesterTransactor) SetLatestPriceSequenceNumber(opts *bind.TransactOpts, seqNr uint64) (*types.Transaction, error) { + return _CCIPReaderTester.contract.Transact(opts, "setLatestPriceSequenceNumber", seqNr) +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) SetLatestPriceSequenceNumber(seqNr uint64) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.SetLatestPriceSequenceNumber(&_CCIPReaderTester.TransactOpts, seqNr) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) SetLatestPriceSequenceNumber(seqNr uint64) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.SetLatestPriceSequenceNumber(&_CCIPReaderTester.TransactOpts, seqNr) +} + func (_CCIPReaderTester *CCIPReaderTesterTransactor) SetSourceChainConfig(opts *bind.TransactOpts, sourceChainSelector uint64, sourceChainConfig OffRampSourceChainConfig) (*types.Transaction, error) { return _CCIPReaderTester.contract.Transact(opts, "setSourceChainConfig", sourceChainSelector, sourceChainConfig) } @@ -817,6 +851,8 @@ type CCIPReaderTesterInterface interface { GetInboundNonce(opts *bind.CallOpts, sourceChainSelector uint64, sender []byte) (uint64, error) + GetLatestPriceSequenceNumber(opts *bind.CallOpts) (uint64, error) + GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (OffRampSourceChainConfig, error) EmitCCIPMessageSent(opts *bind.TransactOpts, destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) @@ -829,6 +865,8 @@ type CCIPReaderTesterInterface interface { SetInboundNonce(opts *bind.TransactOpts, sourceChainSelector uint64, testNonce uint64, sender []byte) (*types.Transaction, error) + SetLatestPriceSequenceNumber(opts *bind.TransactOpts, seqNr uint64) (*types.Transaction, error) + SetSourceChainConfig(opts *bind.TransactOpts, sourceChainSelector uint64, sourceChainConfig OffRampSourceChainConfig) (*types.Transaction, error) FilterCCIPMessageSent(opts *bind.FilterOpts, destChainSelector []uint64, sequenceNumber []uint64) (*CCIPReaderTesterCCIPMessageSentIterator, error) diff --git a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go index 1d28c85f997..1f64166ac74 100644 --- a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go +++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go @@ -156,8 +156,8 @@ type KeystoneFeedsPermissionHandlerPermission struct { } var FeeQuoterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minFeeUSDCents\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint256\"}],\"name\":\"InvalidFeeRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint256\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"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\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"onRampTokenTransfers\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b50604051620078f0380380620078f083398101604081905262000034916200189c565b85336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620001d0565b5050604080518082018252828152815160008152602080820190935291810191909152620000b8906200024a565b5060208701516001600160a01b03161580620000dc575086516001600160601b0316155b80620000f05750604087015163ffffffff16155b156200010f5760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c052805160008152918201905262000155908662000399565b6200016084620004e1565b6200016b81620005d9565b620001768262000a45565b60408051600080825260208201909252620001c391859190620001bc565b6040805180820190915260008082526020820152815260200190600190039081620001945790505b5062000b11565b5050505050505062001b5a565b336001600160a01b03821603620001fa57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b8151811015620002da576000828281518110620002735762000273620019bb565b602090810291909101015190506200028d60028262000e97565b15620002d0576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010162000252565b50815160005b815181101562000393576000828281518110620003015762000301620019bb565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200033f576040516342bcdf7f60e11b815260040160405180910390fd5b6200034c60028262000eb7565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101620002e0565b50505050565b60005b82518110156200043a57620003d8838281518110620003bf57620003bf620019bb565b6020026020010151600b62000ece60201b90919060201c565b156200043157828181518110620003f357620003f3620019bb565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6001016200039c565b5060005b8151811015620004dc576200047a828281518110620004615762000461620019bb565b6020026020010151600b62000eb760201b90919060201c565b15620004d357818181518110620004955762000495620019bb565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b6001016200043e565b505050565b60005b8151811015620005d5576000828281518110620005055762000505620019bb565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a0180518589018051949098166001600160a81b03199093168317600160a01b60ff928316021760ff60a81b1916600160a81b9415159490940293909317909355835190815291511697810197909752915115159186019190915292945090929091907fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf9060600160405180910390a2505050806001019050620004e4565b5050565b60005b8151811015620005d5576000828281518110620005fd57620005fd620019bb565b6020026020010151905060008383815181106200061e576200061e620019bb565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000657575061016081015163ffffffff16155b806200067957506102008101516001600160e01b031916630a04b54b60e21b14155b80620006995750806060015163ffffffff1681610160015163ffffffff16115b15620006c85760405163c35aa79d60e01b81526001600160401b03831660048201526024015b60405180910390fd5b6001600160401b038216600090815260096020526040812060010154600160a81b900460e01b6001600160e01b03191690036200074857816001600160401b03167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda46265826040516200073a9190620019d1565b60405180910390a26200078c565b816001600160401b03167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a83582604051620007839190620019d1565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050620005dc565b60005b8151811015620005d557600082828151811062000a695762000a69620019bb565b6020026020010151600001519050600083838151811062000a8e5762000a8e620019bb565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a48565b60005b825181101562000dd157600083828151811062000b355762000b35620019bb565b6020026020010151905060008160000151905060005b82602001515181101562000dc25760008360200151828151811062000b745762000b74620019bb565b602002602001015160200151905060008460200151838151811062000b9d5762000b9d620019bb565b6020026020010151600001519050816020015163ffffffff16826000015163ffffffff161062000bf857815160208301516040516305a7b3d160e11b815263ffffffff928316600482015291166024820152604401620006bf565b602063ffffffff16826080015163ffffffff16101562000c495760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff9091166024820152604401620006bf565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000daf908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b4b565b50505080600101905062000b14565b5060005b8151811015620004dc57600082828151811062000df65762000df6620019bb565b6020026020010151600001519050600083838151811062000e1b5762000e1b620019bb565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000dd5565b600062000eae836001600160a01b03841662000ee5565b90505b92915050565b600062000eae836001600160a01b03841662000fe9565b600062000eae836001600160a01b0384166200103b565b6000818152600183016020526040812054801562000fde57600062000f0c60018362001b22565b855490915060009062000f229060019062001b22565b905081811462000f8e57600086600001828154811062000f465762000f46620019bb565b906000526020600020015490508087600001848154811062000f6c5762000f6c620019bb565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000fa25762000fa262001b44565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000eb1565b600091505062000eb1565b6000818152600183016020526040812054620010325750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000eb1565b50600062000eb1565b6000818152600183016020526040812054801562000fde5760006200106260018362001b22565b8554909150600090620010789060019062001b22565b905080821462000f8e57600086600001828154811062000f465762000f46620019bb565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620010d757620010d76200109c565b60405290565b604080519081016001600160401b0381118282101715620010d757620010d76200109c565b60405160c081016001600160401b0381118282101715620010d757620010d76200109c565b60405161022081016001600160401b0381118282101715620010d757620010d76200109c565b604051601f8201601f191681016001600160401b03811182821017156200117857620011786200109c565b604052919050565b80516001600160a01b03811681146200119857600080fd5b919050565b805163ffffffff811681146200119857600080fd5b600060608284031215620011c557600080fd5b620011cf620010b2565b82519091506001600160601b0381168114620011ea57600080fd5b8152620011fa6020830162001180565b60208201526200120d604083016200119d565b604082015292915050565b60006001600160401b038211156200123457620012346200109c565b5060051b60200190565b600082601f8301126200125057600080fd5b8151602062001269620012638362001218565b6200114d565b8083825260208201915060208460051b8701019350868411156200128c57600080fd5b602086015b84811015620012b357620012a58162001180565b835291830191830162001291565b509695505050505050565b805180151581146200119857600080fd5b600082601f830112620012e157600080fd5b81516020620012f4620012638362001218565b82815260079290921b840181019181810190868411156200131457600080fd5b8286015b84811015620012b3578088036080811215620013345760008081fd5b6200133e620010dd565b620013498362001180565b8152606080601f1984011215620013605760008081fd5b6200136a620010b2565b92506200137987850162001180565b835260408085015160ff81168114620013925760008081fd5b84890152620013a3858301620012be565b90840152508086019190915283529183019160800162001318565b80516001600160401b03811681146200119857600080fd5b805161ffff811681146200119857600080fd5b600082601f830112620013fb57600080fd5b815160206200140e620012638362001218565b82815260059290921b840181019181810190868411156200142e57600080fd5b8286015b84811015620012b35780516001600160401b03808211156200145357600080fd5b908801906040601f19838c0381018213156200146e57600080fd5b62001478620010dd565b62001485898601620013be565b815282850151848111156200149957600080fd5b8086019550508c603f860112620014af57600080fd5b888501519350620014c4620012638562001218565b84815260e09094028501830193898101908e861115620014e357600080fd5b958401955b85871015620015bc57868f0360e08112156200150357600080fd5b6200150d620010dd565b620015188962001180565b815260c086830112156200152b57600080fd5b6200153562001102565b9150620015448d8a016200119d565b825262001553878a016200119d565b8d8301526200156560608a01620013d6565b878301526200157760808a016200119d565b60608301526200158a60a08a016200119d565b60808301526200159d60c08a01620012be565b60a0830152808d0191909152825260e09690960195908a0190620014e8565b828b01525087525050509284019250830162001432565b600082601f830112620015e557600080fd5b81516020620015f8620012638362001218565b82815260069290921b840181019181810190868411156200161857600080fd5b8286015b84811015620012b35760408189031215620016375760008081fd5b62001641620010dd565b6200164c8262001180565b81526200165b858301620013be565b818601528352918301916040016200161c565b80516001600160e01b0319811681146200119857600080fd5b600082601f8301126200169957600080fd5b81516020620016ac620012638362001218565b8281526102409283028501820192828201919087851115620016cd57600080fd5b8387015b858110156200188f5780890382811215620016ec5760008081fd5b620016f6620010dd565b6200170183620013be565b815261022080601f1984011215620017195760008081fd5b6200172362001127565b925062001732888501620012be565b8352604062001743818601620013d6565b898501526060620017568187016200119d565b82860152608091506200176b8287016200119d565b9085015260a06200177e8682016200119d565b8286015260c0915062001793828701620013d6565b9085015260e0620017a68682016200119d565b828601526101009150620017bc828701620013d6565b90850152610120620017d0868201620013d6565b828601526101409150620017e6828701620013d6565b90850152610160620017fa8682016200119d565b828601526101809150620018108287016200119d565b908501526101a062001824868201620013be565b828601526101c091506200183a8287016200119d565b908501526101e06200184e8682016200119d565b82860152610200915062001864828701620012be565b90850152620018758583016200166e565b9084015250808701919091528452928401928101620016d1565b5090979650505050505050565b6000806000806000806000610120888a031215620018b957600080fd5b620018c58989620011b2565b60608901519097506001600160401b0380821115620018e357600080fd5b620018f18b838c016200123e565b975060808a01519150808211156200190857600080fd5b620019168b838c016200123e565b965060a08a01519150808211156200192d57600080fd5b6200193b8b838c01620012cf565b955060c08a01519150808211156200195257600080fd5b620019608b838c01620013e9565b945060e08a01519150808211156200197757600080fd5b620019858b838c01620015d3565b93506101008a01519150808211156200199d57600080fd5b50620019ac8a828b0162001687565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b81511515815261022081016020830151620019f2602084018261ffff169052565b50604083015162001a0b604084018263ffffffff169052565b50606083015162001a24606084018263ffffffff169052565b50608083015162001a3d608084018263ffffffff169052565b5060a083015162001a5460a084018261ffff169052565b5060c083015162001a6d60c084018263ffffffff169052565b5060e083015162001a8460e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b8181038181111562000eb157634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615d4362001bad600039600081816102fa01526117ba0152600081816102be01528181610ed50152610f3501526000818161028a01528181610f5e0152610fce0152615d436000f3fe608060405234801561001057600080fd5b50600436106101d95760003560e01c806379ba509711610104578063bf78e03f116100a2578063d8694ccd11610071578063d8694ccd14610ad6578063f2fde38b14610ae9578063fbe3f77814610afc578063ffdb4b3714610b0f57600080fd5b8063bf78e03f146109d5578063cdc73d5114610ab3578063d02641a014610abb578063d63d3af214610ace57600080fd5b806382b49eb0116100de57806382b49eb0146108175780638da5cb5b1461098757806391a2749a146109af578063a69c64c0146109c257600080fd5b806379ba5097146107e95780637afac322146107f1578063805f21321461080457600080fd5b806341ed29e71161017c578063514e8cff1161014b578063514e8cff146104845780636cb5f3dd146105275780636def4ce71461053a578063770e2dc4146107d657600080fd5b806341ed29e7146103ee578063430d138c1461040157806345ac924d146104245780634ab35b0b1461044457600080fd5b8063181f5a77116101b8578063181f5a77146103735780632451a627146103bc578063325c868e146103d15780633937306f146103d957600080fd5b806241e5be146101de578063061877e31461020457806306285c691461025d575b600080fd5b6101f16101ec36600461440b565b610b57565b6040519081526020015b60405180910390f35b610244610212366004614447565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101fb565b610327604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101fb565b6103af6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101fb91906144c6565b6103c4610bc5565b6040516101fb91906144d9565b6101f1602481565b6103ec6103e7366004614533565b610bd6565b005b6103ec6103fc3660046146df565b610e8b565b61041461040f3660046148ca565b610ecd565b6040516101fb94939291906149be565b610437610432366004614a5d565b6110dd565b6040516101fb9190614a9f565b610457610452366004614447565b6111a8565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b61051a610492366004614b1a565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101fb9190614b35565b6103ec610535366004614bc6565b6111b3565b6107c9610548366004614b1a565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161022081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a0850152710100000000000000000000000000000000008304871660c08501527501000000000000000000000000000000000000000000808404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c01000000000000000000000000860485166101a083015270010000000000000000000000000000000086049094166101c082015274010000000000000000000000000000000000000000850490911615156101e08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b1661020082015290565b6040516101fb9190614de6565b6103ec6107e4366004614fe4565b6111c7565b6103ec6111d9565b6103ec6107ff3660046152fe565b6112a7565b6103ec610812366004615362565b6112b9565b6109276108253660046153ce565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101fb9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60015460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b6103ec6109bd3660046153f8565b6116f5565b6103ec6109d0366004615489565b611706565b610a766109e3366004614447565b60408051606080820183526000808352602080840182905292840181905273ffffffffffffffffffffffffffffffffffffffff9485168152600783528390208351918201845254938416815260ff74010000000000000000000000000000000000000000850481169282019290925275010000000000000000000000000000000000000000009093041615159082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260208084015160ff1690820152918101511515908201526060016101fb565b6103c4611717565b61051a610ac9366004614447565b611723565b6101f1601281565b6101f1610ae436600461554e565b6118d8565b6103ec610af7366004614447565b611e10565b6103ec610b0a3660046155b2565b611e21565b610b22610b1d3660046156d2565b611e32565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101fb565b6000610b6282611eea565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b8985611eea565b610bb1907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168561572b565b610bbb9190615742565b90505b9392505050565b6060610bd16002611f84565b905090565b610bde611f91565b6000610bea828061577d565b9050905060005b81811015610d34576000610c05848061577d565b83818110610c1557610c156157e5565b905060400201803603810190610c2b9190615840565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610d239290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610bf1565b506000610d44602084018461577d565b9050905060005b81811015610e85576000610d62602086018661577d565b83818110610d7257610d726157e5565b905060400201803603810190610d88919061587d565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610e749290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610d4b565b50505050565b610e93611fd6565b60005b8151811015610ec957610ec1828281518110610eb457610eb46157e5565b6020026020010151612027565b600101610e96565b5050565b6000806060807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff1603610f2e578a9350610f5c565b610f598c8c7f0000000000000000000000000000000000000000000000000000000000000000610b57565b93505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16841115611000576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018590526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b60405180910390fd5b67ffffffffffffffff8d1660009081526009602052604081206001015463ffffffff169061102f8c8c846121f9565b9050806020015194506110458f8b8b8b8b6123a2565b925085856110c5836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b95509550955050509950995099509995505050505050565b60608160008167ffffffffffffffff8111156110fb576110fb61456e565b60405190808252806020026020018201604052801561114057816020015b60408051808201909152600080825260208201528152602001906001900390816111195790505b50905060005b8281101561119d57611178868683818110611163576111636157e5565b9050602002016020810190610ac99190614447565b82828151811061118a5761118a6157e5565b6020908102919091010152600101611146565b509150505b92915050565b60006111a282611eea565b6111bb611fd6565b6111c481612725565b50565b6111cf611fd6565b610ec98282612bf7565b60005473ffffffffffffffffffffffffffffffffffffffff16331461122a576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6112af611fd6565b610ec9828261306d565b60008060006112fd87878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506131b492505050565b92509250925061130f338385846131cf565b600061131d858701876158a0565b905060005b81518110156116ea57600060076000848481518110611343576113436157e5565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff908116835282820193909352604091820160002082516060810184529054938416815260ff740100000000000000000000000000000000000000008504811692820192909252750100000000000000000000000000000000000000000090930416151590820181905290915061143e578282815181106113e7576113e76157e5565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610ff7565b600061148b6012836020015186868151811061145c5761145c6157e5565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16613327565b9050600660008585815181106114a3576114a36157e5565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff16848481518110611515576115156157e5565b60200260200101516040015163ffffffff1610156115345750506116e2565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152602001858581518110611575576115756157e5565b60200260200101516040015163ffffffff16815250600660008686815181106115a0576115a06157e5565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790558351849084908110611638576116386157e5565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a8286868151811061168e5761168e6157e5565b6020026020010151604001516040516116d79291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a250505b600101611322565b505050505050505050565b6116fd611fd6565b6111c4816133ea565b61170e611fd6565b6111c481613576565b6060610bd1600b611f84565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169183018290527f000000000000000000000000000000000000000000000000000000000000000016906117e59042615967565b10156117f15792915050565b73ffffffffffffffffffffffffffffffffffffffff80841660009081526007602090815260409182902082516060810184529054938416815260ff74010000000000000000000000000000000000000000850481169282019290925275010000000000000000000000000000000000000000009093041615801591830191909152806118925750805173ffffffffffffffffffffffffffffffffffffffff16155b1561189e575092915050565b60006118a982613660565b9050826020015163ffffffff16816020015163ffffffff1610156118cd57826118cf565b805b95945050505050565b67ffffffffffffffff8083166000908152600960209081526040808320815161022081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a0860152710100000000000000000000000000000000008404871660c08601527501000000000000000000000000000000000000000000808504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c01000000000000000000000000880485166101a084015270010000000000000000000000000000000088049094166101c083015274010000000000000000000000000000000000000000870490931615156101e08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b16610200840152909190611b12576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610ff7565b611b2d611b256080850160608601614447565b600b906137f2565b611b8c57611b416080840160608501614447565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610ff7565b6000611b9b604085018561577d565b9150611bf7905082611bb0602087018761597a565b905083611bbd888061597a565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061382192505050565b6000611c11611c0c6080870160608801614447565b611eea565b90506000611c2487856101c001516138de565b9050600080808515611c6457611c58878b611c4560808d0160608e01614447565b88611c5360408f018f61577d565b6139de565b91945092509050611c84565b6101a0870151611c819063ffffffff16662386f26fc1000061572b565b92505b61010087015160009061ffff1615611cc857611cc5886dffffffffffffffffffffffffffff607088901c16611cbc60208e018e61597a565b90508a86613cb6565b90505b61018088015160009067ffffffffffffffff16611cf1611ceb60808e018e61597a565b8c613d66565b600001518563ffffffff168b60a0015161ffff168e8060200190611d15919061597a565b611d2092915061572b565b8c6080015163ffffffff16611d3591906159df565b611d3f91906159df565b611d4991906159df565b611d63906dffffffffffffffffffffffffffff891661572b565b611d6d919061572b565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f6060016020810190611da79190614447565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054611de29067ffffffffffffffff168961572b565b611dec91906159df565b611df691906159df565b611e009190615742565b9c9b505050505050505050505050565b611e18611fd6565b6111c481613e27565b611e29611fd6565b6111c481613eeb565b67ffffffffffffffff8116600090815260096020526040812054819060ff16611e93576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610ff7565b611e9c84611eea565b67ffffffffffffffff8416600090815260096020526040902060010154611ede908590700100000000000000000000000000000000900463ffffffff166138de565b915091505b9250929050565b600080611ef683611723565b9050806020015163ffffffff1660001480611f2e575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15611f7d576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610ff7565b5192915050565b60606000610bbe8361403d565b611f9c6002336137f2565b611fd4576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610ff7565b565b60015473ffffffffffffffffffffffffffffffffffffffff163314611fd4576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006120e082600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3906121ed908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b6040805180820190915260008082526020820152600083900361223a57506040805180820190915267ffffffffffffffff8216815260006020820152610bbe565b600061224684866159f2565b905060006122578560048189615a38565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f000000000000000000000000000000000000000000000000000000000016122f457808060200190518101906122eb9190615a62565b92505050610bbe565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016123705760405180604001604052808280602001905181019061235c9190615a8e565b815260006020909101529250610bbe915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff808616600090815260096020526040902060010154606091750100000000000000000000000000000000000000000090910460e01b9085908111156123f2576123f261456e565b60405190808252806020026020018201604052801561242557816020015b60608152602001906001900390816124105790505b50915060005b8581101561271a576000858583818110612447576124476157e5565b61245d9260206040909202019081019150614447565b90506000888884818110612473576124736157e5565b90506020028101906124859190615aa7565b61249390604081019061597a565b91505060208111156125435767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115612543576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610ff7565b6125b3848a8a86818110612559576125596157e5565b905060200281019061256b9190615aa7565b61257990602081019061597a565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061409992505050565b67ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684528252808320815160c081018352905463ffffffff8082168352640100000000820481169483019490945268010000000000000000810461ffff16928201929092526a01000000000000000000008204831660608201526e010000000000000000000000000000820490921660808301527201000000000000000000000000000000000000900460ff16151560a082018190529091906126c55767ffffffffffffffff8c166000908152600960205260409020547b01000000000000000000000000000000000000000000000000000000900463ffffffff166126cb565b81606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052878681518110612700576127006157e5565b60200260200101819052505050505080600101905061242b565b505095945050505050565b60005b8151811015610ec9576000828281518110612745576127456157e5565b602002602001015190506000838381518110612763576127636157e5565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061279c575061016081015163ffffffff16155b806127ee57506102008101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b8061280d5750806060015163ffffffff1681610160015163ffffffff16115b15612850576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610ff7565b67ffffffffffffffff82166000908152600960205260408120600101547501000000000000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036128f8578167ffffffffffffffff167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda46265826040516128eb9190614de6565b60405180910390a261293b565b8167ffffffffffffffff167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a835826040516129329190614de6565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050612728565b60005b8251811015612f84576000838281518110612c1757612c176157e5565b6020026020010151905060008160000151905060005b826020015151811015612f7657600083602001518281518110612c5257612c526157e5565b6020026020010151602001519050600084602001518381518110612c7857612c786157e5565b6020026020010151600001519050816020015163ffffffff16826000015163ffffffff1610612cea57815160208301516040517f0b4f67a200000000000000000000000000000000000000000000000000000000815263ffffffff928316600482015291166024820152604401610ff7565b602063ffffffff16826080015163ffffffff161015612d5f5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610ff7565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612f64908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612c2d565b505050806001019050612bfa565b5060005b8151811015613068576000828281518110612fa557612fa56157e5565b60200260200101516000015190506000838381518110612fc757612fc76157e5565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612f88565b505050565b60005b8251811015613110576130a683828151811061308e5761308e6157e5565b6020026020010151600b6140eb90919063ffffffff16565b15613108578281815181106130bd576130bd6157e5565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101613070565b5060005b81518110156130685761314a828281518110613132576131326157e5565b6020026020010151600b61410d90919063ffffffff16565b156131ac57818181518110613161576131616157e5565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101613114565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16613320576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610ff7565b5050505050565b6000806133348486615ae5565b9050600060248260ff16111561336e57613352602460ff8416615967565b61335d90600a615c1e565b6133679085615742565b9050613394565b61337c60ff83166024615967565b61338790600a615c1e565b613391908561572b565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156118cf576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160005b815181101561348557600082828151811061340f5761340f6157e5565b6020026020010151905061342d81600261412f90919063ffffffff16565b1561347c5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b506001016133f2565b50815160005b8151811015610e855760008282815181106134a8576134a86157e5565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613518576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61352360028261410d565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010161348b565b60005b8151811015610ec9576000828281518110613596576135966157e5565b602002602001015160000151905060008383815181106135b8576135b86157e5565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a25050600101613579565b60408051808201909152600080825260208201526000826000015190506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156136cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ef9190615c44565b509350509250506000821215613731576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006137b08473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613781573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137a59190615c94565b876020015185613327565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff909216602083015250949350505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610bbe565b836040015163ffffffff1683111561387a5760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610ff7565b836020015161ffff168211156138cf5760208401516040517fd88dddd60000000000000000000000000000000000000000000000000000000081526004810184905261ffff9091166024820152604401610ff7565b610e8584610200015182614099565b67ffffffffffffffff821660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116825263ffffffff7c0100000000000000000000000000000000000000000000000000000000909104811692820192909252908316156139d6576000816020015163ffffffff16426139739190615967565b90508363ffffffff168111156139d4576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff8516602482015260448101829052606401610ff7565b505b519392505050565b6000808083815b81811015613ca8576000878783818110613a0157613a016157e5565b905060400201803603810190613a179190615cb1565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613b37576101208d0151613b049061ffff16662386f26fc1000061572b565b613b0e90886159df565b96508c610140015186613b219190615cea565b9550613b2e602086615cea565b94505050613ca0565b604081015160009061ffff1615613bf05760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613b93578351613b8c90611eea565b9050613b96565b508a5b620186a0836040015161ffff16613bd88660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661415190919063ffffffff16565b613be2919061572b565b613bec9190615742565b9150505b6060820151613bff9088615cea565b9650816080015186613c119190615cea565b8251909650600090613c309063ffffffff16662386f26fc1000061572b565b905080821015613c4f57613c44818a6159df565b985050505050613ca0565b6000836020015163ffffffff16662386f26fc10000613c6e919061572b565b905080831115613c8e57613c82818b6159df565b99505050505050613ca0565b613c98838b6159df565b995050505050505b6001016139e5565b505096509650969350505050565b60008063ffffffff8316613ccc6101208661572b565b613cd8876101e06159df565b613ce291906159df565b613cec91906159df565b905060008760c0015163ffffffff168860e0015161ffff1683613d0f919061572b565b613d1991906159df565b61010089015190915061ffff16613d406dffffffffffffffffffffffffffff89168361572b565b613d4a919061572b565b613d5a90655af3107a400061572b565b98975050505050505050565b60408051808201909152600080825260208201526000613d92858585610160015163ffffffff166121f9565b9050826060015163ffffffff1681600001511115613ddc576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015613df057508060200151155b15610bbb576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613e76576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b8151811015610ec9576000828281518110613f0b57613f0b6157e5565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a0180518589018051949098167fffffffffffffffffffffff00000000000000000000000000000000000000000090931683177401000000000000000000000000000000000000000060ff92831602177fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000009415159490940293909317909355835190815291511697810197909752915115159186019190915292945090929091907fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf9060600160405180910390a2505050806001019050613eee565b60608160000180548060200260200160405190810160405280929190818152602001828054801561408d57602002820191906000526020600020905b815481526020019060010190808311614079575b50505050509050919050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610ec9576130688161418e565b6000610bbe8373ffffffffffffffffffffffffffffffffffffffff8416614241565b6000610bbe8373ffffffffffffffffffffffffffffffffffffffff841661433b565b6000610bbe8373ffffffffffffffffffffffffffffffffffffffff841661438a565b6000670de0b6b3a7640000614184837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff861661572b565b610bbe9190615742565b600081516020146141cd57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610ff791906144c6565b6000828060200190518101906141e39190615a8e565b905073ffffffffffffffffffffffffffffffffffffffff811180614208575061040081105b156111a257826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610ff791906144c6565b6000818152600183016020526040812054801561432a576000614265600183615967565b855490915060009061427990600190615967565b90508082146142de576000866000018281548110614299576142996157e5565b90600052602060002001549050808760000184815481106142bc576142bc6157e5565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806142ef576142ef615d07565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506111a2565b60009150506111a2565b5092915050565b6000818152600183016020526040812054614382575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556111a2565b5060006111a2565b6000818152600183016020526040812054801561432a5760006143ae600183615967565b85549091506000906143c290600190615967565b90508181146142de576000866000018281548110614299576142996157e5565b803573ffffffffffffffffffffffffffffffffffffffff8116811461440657600080fd5b919050565b60008060006060848603121561442057600080fd5b614429846143e2565b92506020840135915061443e604085016143e2565b90509250925092565b60006020828403121561445957600080fd5b610bbe826143e2565b6000815180845260005b818110156144885760208185018101518683018201520161446c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610bbe6020830184614462565b6020808252825182820181905260009190848201906040850190845b8181101561452757835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016144f5565b50909695505050505050565b60006020828403121561454557600080fd5b813567ffffffffffffffff81111561455c57600080fd5b820160408185031215610bbe57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156145c0576145c061456e565b60405290565b6040805190810167ffffffffffffffff811182821017156145c0576145c061456e565b604051610220810167ffffffffffffffff811182821017156145c0576145c061456e565b60405160c0810167ffffffffffffffff811182821017156145c0576145c061456e565b6040516060810167ffffffffffffffff811182821017156145c0576145c061456e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561469a5761469a61456e565b604052919050565b600067ffffffffffffffff8211156146bc576146bc61456e565b5060051b60200190565b80151581146111c457600080fd5b8035614406816146c6565b600060208083850312156146f257600080fd5b823567ffffffffffffffff81111561470957600080fd5b8301601f8101851361471a57600080fd5b803561472d614728826146a2565b614653565b81815260a0918202830184019184820191908884111561474c57600080fd5b938501935b8385101561481f5780858a0312156147695760008081fd5b61477161459d565b61477a866143e2565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146147af5760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146147e85760008081fd5b9082015260606147f98782016143e2565b9082015260808681013561480c816146c6565b9082015283529384019391850191614751565b50979650505050505050565b803567ffffffffffffffff8116811461440657600080fd5b60008083601f84011261485557600080fd5b50813567ffffffffffffffff81111561486d57600080fd5b602083019150836020828501011115611ee357600080fd5b60008083601f84011261489757600080fd5b50813567ffffffffffffffff8111156148af57600080fd5b6020830191508360208260051b8501011115611ee357600080fd5b600080600080600080600080600060c08a8c0312156148e857600080fd5b6148f18a61482b565b98506148ff60208b016143e2565b975060408a0135965060608a013567ffffffffffffffff8082111561492357600080fd5b61492f8d838e01614843565b909850965060808c013591508082111561494857600080fd5b6149548d838e01614885565b909650945060a08c013591508082111561496d57600080fd5b818c0191508c601f83011261498157600080fd5b81358181111561499057600080fd5b8d60208260061b85010111156149a557600080fd5b6020830194508093505050509295985092959850929598565b8481526000602085151581840152608060408401526149e06080840186614462565b8381036060850152845180825282820190600581901b8301840184880160005b83811015614a4c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552614a3a838351614462565b94870194925090860190600101614a00565b50909b9a5050505050505050505050565b60008060208385031215614a7057600080fd5b823567ffffffffffffffff811115614a8757600080fd5b614a9385828601614885565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614b0d57614afd84835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614abc565b5091979650505050505050565b600060208284031215614b2c57600080fd5b610bbe8261482b565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016111a2565b803561ffff8116811461440657600080fd5b803563ffffffff8116811461440657600080fd5b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461440657600080fd5b60006020808385031215614bd957600080fd5b823567ffffffffffffffff811115614bf057600080fd5b8301601f81018513614c0157600080fd5b8035614c0f614728826146a2565b8181526102409182028301840191848201919088841115614c2f57600080fd5b938501935b8385101561481f5784890381811215614c4d5760008081fd5b614c556145c6565b614c5e8761482b565b8152610220807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084011215614c935760008081fd5b614c9b6145e9565b9250614ca88989016146d4565b83526040614cb7818a01614b70565b8a8501526060614cc8818b01614b82565b8286015260809150614cdb828b01614b82565b9085015260a0614cec8a8201614b82565b8286015260c09150614cff828b01614b70565b9085015260e0614d108a8201614b82565b828601526101009150614d24828b01614b70565b90850152610120614d368a8201614b70565b828601526101409150614d4a828b01614b70565b90850152610160614d5c8a8201614b82565b828601526101809150614d70828b01614b82565b908501526101a0614d828a820161482b565b828601526101c09150614d96828b01614b82565b908501526101e0614da88a8201614b82565b828601526102009150614dbc828b016146d4565b90850152614dcb898301614b96565b90840152508088019190915283529384019391850191614c34565b81511515815261022081016020830151614e06602084018261ffff169052565b506040830151614e1e604084018263ffffffff169052565b506060830151614e36606084018263ffffffff169052565b506080830151614e4e608084018263ffffffff169052565b5060a0830151614e6460a084018261ffff169052565b5060c0830151614e7c60c084018263ffffffff169052565b5060e0830151614e9260e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b600082601f830112614f5d57600080fd5b81356020614f6d614728836146a2565b82815260069290921b84018101918181019086841115614f8c57600080fd5b8286015b84811015614fd95760408189031215614fa95760008081fd5b614fb16145c6565b614fba8261482b565b8152614fc78583016143e2565b81860152835291830191604001614f90565b509695505050505050565b60008060408385031215614ff757600080fd5b67ffffffffffffffff8335111561500d57600080fd5b83601f84358501011261501f57600080fd5b61502f61472884358501356146a2565b8335840180358083526020808401939260059290921b9091010186101561505557600080fd5b602085358601015b85358601803560051b016020018110156152625767ffffffffffffffff8135111561508757600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a030112156150c057600080fd5b6150c86145c6565b6150d46020830161482b565b815267ffffffffffffffff604083013511156150ef57600080fd5b88603f60408401358401011261510457600080fd5b61511a61472860206040850135850101356146a2565b6020604084810135850182810135808552928401939260e00201018b101561514157600080fd5b6040808501358501015b6040858101358601602081013560e00201018110156152435760e0818d03121561517457600080fd5b61517c6145c6565b615185826143e2565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f030112156151b957600080fd5b6151c161460d565b6151cd60208401614b82565b81526151db60408401614b82565b60208201526151ec60608401614b70565b60408201526151fd60808401614b82565b606082015261520e60a08401614b82565b608082015261522060c08401356146c6565b60c083013560a0820152602082810191909152908452929092019160e00161514b565b508060208401525050808552505060208301925060208101905061505d565b5092505067ffffffffffffffff6020840135111561527f57600080fd5b61528f8460208501358501614f4c565b90509250929050565b600082601f8301126152a957600080fd5b813560206152b9614728836146a2565b8083825260208201915060208460051b8701019350868411156152db57600080fd5b602086015b84811015614fd9576152f1816143e2565b83529183019183016152e0565b6000806040838503121561531157600080fd5b823567ffffffffffffffff8082111561532957600080fd5b61533586838701615298565b9350602085013591508082111561534b57600080fd5b5061535885828601615298565b9150509250929050565b6000806000806040858703121561537857600080fd5b843567ffffffffffffffff8082111561539057600080fd5b61539c88838901614843565b909650945060208701359150808211156153b557600080fd5b506153c287828801614843565b95989497509550505050565b600080604083850312156153e157600080fd5b6153ea8361482b565b915061528f602084016143e2565b60006020828403121561540a57600080fd5b813567ffffffffffffffff8082111561542257600080fd5b908301906040828603121561543657600080fd5b61543e6145c6565b82358281111561544d57600080fd5b61545987828601615298565b82525060208301358281111561546e57600080fd5b61547a87828601615298565b60208301525095945050505050565b6000602080838503121561549c57600080fd5b823567ffffffffffffffff8111156154b357600080fd5b8301601f810185136154c457600080fd5b80356154d2614728826146a2565b81815260069190911b820183019083810190878311156154f157600080fd5b928401925b82841015615543576040848903121561550f5760008081fd5b6155176145c6565b615520856143e2565b815261552d86860161482b565b81870152825260409390930192908401906154f6565b979650505050505050565b6000806040838503121561556157600080fd5b61556a8361482b565b9150602083013567ffffffffffffffff81111561558657600080fd5b830160a0818603121561559857600080fd5b809150509250929050565b60ff811681146111c457600080fd5b600060208083850312156155c557600080fd5b823567ffffffffffffffff8111156155dc57600080fd5b8301601f810185136155ed57600080fd5b80356155fb614728826146a2565b81815260079190911b8201830190838101908783111561561a57600080fd5b928401925b828410156155435783880360808112156156395760008081fd5b6156416145c6565b61564a866143e2565b81526060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08401121561567e5760008081fd5b615686614630565b92506156938888016143e2565b83526040808801356156a4816155a3565b848a015290870135906156b6826146c6565b830152808701919091528252608093909301929084019061561f565b600080604083850312156156e557600080fd5b6156ee836143e2565b915061528f6020840161482b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176111a2576111a26156fc565b600082615778577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126157b257600080fd5b83018035915067ffffffffffffffff8211156157cd57600080fd5b6020019150600681901b3603821315611ee357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461440657600080fd5b60006040828403121561585257600080fd5b61585a6145c6565b615863836143e2565b815261587160208401615814565b60208201529392505050565b60006040828403121561588f57600080fd5b6158976145c6565b6158638361482b565b600060208083850312156158b357600080fd5b823567ffffffffffffffff8111156158ca57600080fd5b8301601f810185136158db57600080fd5b80356158e9614728826146a2565b8181526060918202830184019184820191908884111561590857600080fd5b938501935b8385101561481f5780858a0312156159255760008081fd5b61592d614630565b615936866143e2565b8152615943878701615814565b878201526040615954818801614b82565b908201528352938401939185019161590d565b818103818111156111a2576111a26156fc565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126159af57600080fd5b83018035915067ffffffffffffffff8211156159ca57600080fd5b602001915036819003821315611ee357600080fd5b808201808211156111a2576111a26156fc565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614f445760049490940360031b84901b1690921692915050565b60008085851115615a4857600080fd5b83861115615a5557600080fd5b5050820193919092039150565b600060408284031215615a7457600080fd5b615a7c6145c6565b825181526020830151615871816146c6565b600060208284031215615aa057600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112615adb57600080fd5b9190910192915050565b60ff81811683821601908111156111a2576111a26156fc565b600181815b80851115615b5757817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615b3d57615b3d6156fc565b80851615615b4a57918102915b93841c9390800290615b03565b509250929050565b600082615b6e575060016111a2565b81615b7b575060006111a2565b8160018114615b915760028114615b9b57615bb7565b60019150506111a2565b60ff841115615bac57615bac6156fc565b50506001821b6111a2565b5060208310610133831016604e8410600b8410161715615bda575081810a6111a2565b615be48383615afe565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615c1657615c166156fc565b029392505050565b6000610bbe8383615b5f565b805169ffffffffffffffffffff8116811461440657600080fd5b600080600080600060a08688031215615c5c57600080fd5b615c6586615c2a565b9450602086015193506040860151925060608601519150615c8860808701615c2a565b90509295509295909350565b600060208284031215615ca657600080fd5b8151610bbe816155a3565b600060408284031215615cc357600080fd5b615ccb6145c6565b615cd4836143e2565b8152602083013560208201528091505092915050565b63ffffffff818116838216019080821115614334576143346156fc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minFeeUSDCents\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint256\"}],\"name\":\"InvalidFeeRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint256\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"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\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"onRampTokenTransfers\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b5060405162007a6838038062007a6883398101604081905262000034916200189c565b85336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620001d0565b5050604080518082018252828152815160008152602080820190935291810191909152620000b8906200024a565b5060208701516001600160a01b03161580620000dc575086516001600160601b0316155b80620000f05750604087015163ffffffff16155b156200010f5760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c052805160008152918201905262000155908662000399565b6200016084620004e1565b6200016b81620005d9565b620001768262000a45565b60408051600080825260208201909252620001c391859190620001bc565b6040805180820190915260008082526020820152815260200190600190039081620001945790505b5062000b11565b5050505050505062001b5a565b336001600160a01b03821603620001fa57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b8151811015620002da576000828281518110620002735762000273620019bb565b602090810291909101015190506200028d60028262000e97565b15620002d0576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010162000252565b50815160005b815181101562000393576000828281518110620003015762000301620019bb565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200033f576040516342bcdf7f60e11b815260040160405180910390fd5b6200034c60028262000eb7565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101620002e0565b50505050565b60005b82518110156200043a57620003d8838281518110620003bf57620003bf620019bb565b6020026020010151600b62000ece60201b90919060201c565b156200043157828181518110620003f357620003f3620019bb565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6001016200039c565b5060005b8151811015620004dc576200047a828281518110620004615762000461620019bb565b6020026020010151600b62000eb760201b90919060201c565b15620004d357818181518110620004955762000495620019bb565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b6001016200043e565b505050565b60005b8151811015620005d5576000828281518110620005055762000505620019bb565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a0180518589018051949098166001600160a81b03199093168317600160a01b60ff928316021760ff60a81b1916600160a81b9415159490940293909317909355835190815291511697810197909752915115159186019190915292945090929091907fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf9060600160405180910390a2505050806001019050620004e4565b5050565b60005b8151811015620005d5576000828281518110620005fd57620005fd620019bb565b6020026020010151905060008383815181106200061e576200061e620019bb565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000657575061016081015163ffffffff16155b806200067957506102008101516001600160e01b031916630a04b54b60e21b14155b80620006995750806060015163ffffffff1681610160015163ffffffff16115b15620006c85760405163c35aa79d60e01b81526001600160401b03831660048201526024015b60405180910390fd5b6001600160401b038216600090815260096020526040812060010154600160a81b900460e01b6001600160e01b03191690036200074857816001600160401b03167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda46265826040516200073a9190620019d1565b60405180910390a26200078c565b816001600160401b03167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a83582604051620007839190620019d1565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050620005dc565b60005b8151811015620005d557600082828151811062000a695762000a69620019bb565b6020026020010151600001519050600083838151811062000a8e5762000a8e620019bb565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a48565b60005b825181101562000dd157600083828151811062000b355762000b35620019bb565b6020026020010151905060008160000151905060005b82602001515181101562000dc25760008360200151828151811062000b745762000b74620019bb565b602002602001015160200151905060008460200151838151811062000b9d5762000b9d620019bb565b6020026020010151600001519050816020015163ffffffff16826000015163ffffffff161062000bf857815160208301516040516305a7b3d160e11b815263ffffffff928316600482015291166024820152604401620006bf565b602063ffffffff16826080015163ffffffff16101562000c495760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff9091166024820152604401620006bf565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000daf908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b4b565b50505080600101905062000b14565b5060005b8151811015620004dc57600082828151811062000df65762000df6620019bb565b6020026020010151600001519050600083838151811062000e1b5762000e1b620019bb565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000dd5565b600062000eae836001600160a01b03841662000ee5565b90505b92915050565b600062000eae836001600160a01b03841662000fe9565b600062000eae836001600160a01b0384166200103b565b6000818152600183016020526040812054801562000fde57600062000f0c60018362001b22565b855490915060009062000f229060019062001b22565b905081811462000f8e57600086600001828154811062000f465762000f46620019bb565b906000526020600020015490508087600001848154811062000f6c5762000f6c620019bb565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000fa25762000fa262001b44565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000eb1565b600091505062000eb1565b6000818152600183016020526040812054620010325750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000eb1565b50600062000eb1565b6000818152600183016020526040812054801562000fde5760006200106260018362001b22565b8554909150600090620010789060019062001b22565b905080821462000f8e57600086600001828154811062000f465762000f46620019bb565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620010d757620010d76200109c565b60405290565b604080519081016001600160401b0381118282101715620010d757620010d76200109c565b60405160c081016001600160401b0381118282101715620010d757620010d76200109c565b60405161022081016001600160401b0381118282101715620010d757620010d76200109c565b604051601f8201601f191681016001600160401b03811182821017156200117857620011786200109c565b604052919050565b80516001600160a01b03811681146200119857600080fd5b919050565b805163ffffffff811681146200119857600080fd5b600060608284031215620011c557600080fd5b620011cf620010b2565b82519091506001600160601b0381168114620011ea57600080fd5b8152620011fa6020830162001180565b60208201526200120d604083016200119d565b604082015292915050565b60006001600160401b038211156200123457620012346200109c565b5060051b60200190565b600082601f8301126200125057600080fd5b8151602062001269620012638362001218565b6200114d565b8083825260208201915060208460051b8701019350868411156200128c57600080fd5b602086015b84811015620012b357620012a58162001180565b835291830191830162001291565b509695505050505050565b805180151581146200119857600080fd5b600082601f830112620012e157600080fd5b81516020620012f4620012638362001218565b82815260079290921b840181019181810190868411156200131457600080fd5b8286015b84811015620012b3578088036080811215620013345760008081fd5b6200133e620010dd565b620013498362001180565b8152606080601f1984011215620013605760008081fd5b6200136a620010b2565b92506200137987850162001180565b835260408085015160ff81168114620013925760008081fd5b84890152620013a3858301620012be565b90840152508086019190915283529183019160800162001318565b80516001600160401b03811681146200119857600080fd5b805161ffff811681146200119857600080fd5b600082601f830112620013fb57600080fd5b815160206200140e620012638362001218565b82815260059290921b840181019181810190868411156200142e57600080fd5b8286015b84811015620012b35780516001600160401b03808211156200145357600080fd5b908801906040601f19838c0381018213156200146e57600080fd5b62001478620010dd565b62001485898601620013be565b815282850151848111156200149957600080fd5b8086019550508c603f860112620014af57600080fd5b888501519350620014c4620012638562001218565b84815260e09094028501830193898101908e861115620014e357600080fd5b958401955b85871015620015bc57868f0360e08112156200150357600080fd5b6200150d620010dd565b620015188962001180565b815260c086830112156200152b57600080fd5b6200153562001102565b9150620015448d8a016200119d565b825262001553878a016200119d565b8d8301526200156560608a01620013d6565b878301526200157760808a016200119d565b60608301526200158a60a08a016200119d565b60808301526200159d60c08a01620012be565b60a0830152808d0191909152825260e09690960195908a0190620014e8565b828b01525087525050509284019250830162001432565b600082601f830112620015e557600080fd5b81516020620015f8620012638362001218565b82815260069290921b840181019181810190868411156200161857600080fd5b8286015b84811015620012b35760408189031215620016375760008081fd5b62001641620010dd565b6200164c8262001180565b81526200165b858301620013be565b818601528352918301916040016200161c565b80516001600160e01b0319811681146200119857600080fd5b600082601f8301126200169957600080fd5b81516020620016ac620012638362001218565b8281526102409283028501820192828201919087851115620016cd57600080fd5b8387015b858110156200188f5780890382811215620016ec5760008081fd5b620016f6620010dd565b6200170183620013be565b815261022080601f1984011215620017195760008081fd5b6200172362001127565b925062001732888501620012be565b8352604062001743818601620013d6565b898501526060620017568187016200119d565b82860152608091506200176b8287016200119d565b9085015260a06200177e8682016200119d565b8286015260c0915062001793828701620013d6565b9085015260e0620017a68682016200119d565b828601526101009150620017bc828701620013d6565b90850152610120620017d0868201620013d6565b828601526101409150620017e6828701620013d6565b90850152610160620017fa8682016200119d565b828601526101809150620018108287016200119d565b908501526101a062001824868201620013be565b828601526101c091506200183a8287016200119d565b908501526101e06200184e8682016200119d565b82860152610200915062001864828701620012be565b90850152620018758583016200166e565b9084015250808701919091528452928401928101620016d1565b5090979650505050505050565b6000806000806000806000610120888a031215620018b957600080fd5b620018c58989620011b2565b60608901519097506001600160401b0380821115620018e357600080fd5b620018f18b838c016200123e565b975060808a01519150808211156200190857600080fd5b620019168b838c016200123e565b965060a08a01519150808211156200192d57600080fd5b6200193b8b838c01620012cf565b955060c08a01519150808211156200195257600080fd5b620019608b838c01620013e9565b945060e08a01519150808211156200197757600080fd5b620019858b838c01620015d3565b93506101008a01519150808211156200199d57600080fd5b50620019ac8a828b0162001687565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b81511515815261022081016020830151620019f2602084018261ffff169052565b50604083015162001a0b604084018263ffffffff169052565b50606083015162001a24606084018263ffffffff169052565b50608083015162001a3d608084018263ffffffff169052565b5060a083015162001a5460a084018261ffff169052565b5060c083015162001a6d60c084018263ffffffff169052565b5060e083015162001a8460e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b8181038181111562000eb157634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615ebb62001bad6000396000818161032801526119170152600081816102ec0152818161103401526110940152600081816102b8015281816110bd015261112d0152615ebb6000f3fe608060405234801561001057600080fd5b50600436106101e45760003560e01c8063770e2dc41161010f578063bf78e03f116100a2578063d8694ccd11610071578063d8694ccd14610b04578063f2fde38b14610b17578063fbe3f77814610b2a578063ffdb4b3714610b3d57600080fd5b8063bf78e03f14610a03578063cdc73d5114610ae1578063d02641a014610ae9578063d63d3af214610afc57600080fd5b806382b49eb0116100de57806382b49eb0146108455780638da5cb5b146109b557806391a2749a146109dd578063a69c64c0146109f057600080fd5b8063770e2dc41461080457806379ba5097146108175780637afac3221461081f578063805f21321461083257600080fd5b80633937306f116101875780634ab35b0b116101565780634ab35b0b14610472578063514e8cff146104b25780636cb5f3dd146105555780636def4ce71461056857600080fd5b80633937306f1461040757806341ed29e71461041c578063430d138c1461042f57806345ac924d1461045257600080fd5b806306285c69116101c357806306285c691461028b578063181f5a77146103a15780632451a627146103ea578063325c868e146103ff57600080fd5b806241e5be146101e957806301ffc9a71461020f578063061877e314610232575b600080fd5b6101fc6101f7366004614568565b610b85565b6040519081526020015b60405180910390f35b61022261021d3660046145d4565b610bf3565b6040519015158152602001610206565b6102726102403660046145ef565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610206565b610355604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff1690820152606001610206565b6103dd6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b604051610206919061466e565b6103f2610d24565b6040516102069190614681565b6101fc602481565b61041a6104153660046146db565b610d35565b005b61041a61042a366004614887565b610fea565b61044261043d366004614a72565b61102c565b6040516102069493929190614b66565b610465610460366004614c05565b61123c565b6040516102069190614c47565b6104856104803660046145ef565b611305565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b6105486104c0366004614cc2565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516102069190614cdd565b61041a610563366004614d3e565b611310565b6107f7610576366004614cc2565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161022081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a0850152710100000000000000000000000000000000008304871660c08501527501000000000000000000000000000000000000000000808404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c01000000000000000000000000860485166101a083015270010000000000000000000000000000000086049094166101c082015274010000000000000000000000000000000000000000850490911615156101e08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b1661020082015290565b6040516102069190614f5e565b61041a61081236600461515c565b611324565b61041a611336565b61041a61082d366004615476565b611404565b61041a6108403660046154da565b611416565b610955610853366004615546565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516102069190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b61041a6109eb366004615570565b611852565b61041a6109fe366004615601565b611863565b610aa4610a113660046145ef565b60408051606080820183526000808352602080840182905292840181905273ffffffffffffffffffffffffffffffffffffffff9485168152600783528390208351918201845254938416815260ff74010000000000000000000000000000000000000000850481169282019290925275010000000000000000000000000000000000000000009093041615159082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260208084015160ff169082015291810151151590820152606001610206565b6103f2611874565b610548610af73660046145ef565b611880565b6101fc601281565b6101fc610b123660046156c6565b611a35565b61041a610b253660046145ef565b611f6d565b61041a610b3836600461572a565b611f7e565b610b50610b4b36600461584a565b611f8f565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201610206565b6000610b9082612047565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610bb785612047565b610bdf907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856158a3565b610be991906158ba565b90505b9392505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f805f2132000000000000000000000000000000000000000000000000000000001480610c8657507fffffffff0000000000000000000000000000000000000000000000000000000082167f9b645f4100000000000000000000000000000000000000000000000000000000145b80610cd257507fffffffff0000000000000000000000000000000000000000000000000000000082167f181f5a7700000000000000000000000000000000000000000000000000000000145b80610d1e57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6060610d3060026120e1565b905090565b610d3d6120ee565b6000610d4982806158f5565b9050905060005b81811015610e93576000610d6484806158f5565b83818110610d7457610d7461595d565b905060400201803603810190610d8a91906159b8565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610e829290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610d50565b506000610ea360208401846158f5565b9050905060005b81811015610fe4576000610ec160208601866158f5565b83818110610ed157610ed161595d565b905060400201803603810190610ee791906159f5565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610fd39290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610eaa565b50505050565b610ff2612133565b60005b8151811015611028576110208282815181106110135761101361595d565b6020026020010151612184565b600101610ff5565b5050565b6000806060807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff160361108d578a93506110bb565b6110b88c8c7f0000000000000000000000000000000000000000000000000000000000000000610b85565b93505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1684111561115f576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018590526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b60405180910390fd5b67ffffffffffffffff8d1660009081526009602052604081206001015463ffffffff169061118e8c8c84612356565b9050806020015194506111a48f8b8b8b8b6124ff565b92508585611224836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b95509550955050509950995099509995505050505050565b60608160008167ffffffffffffffff81111561125a5761125a614716565b60405190808252806020026020018201604052801561129f57816020015b60408051808201909152600080825260208201528152602001906001900390816112785790505b50905060005b828110156112fc576112d78686838181106112c2576112c261595d565b9050602002016020810190610af791906145ef565b8282815181106112e9576112e961595d565b60209081029190910101526001016112a5565b50949350505050565b6000610d1e82612047565b611318612133565b61132181612882565b50565b61132c612133565b6110288282612d54565b60005473ffffffffffffffffffffffffffffffffffffffff163314611387576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61140c612133565b61102882826131ca565b600080600061145a87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061331192505050565b92509250925061146c3383858461332c565b600061147a85870187615a18565b905060005b8151811015611847576000600760008484815181106114a0576114a061595d565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff908116835282820193909352604091820160002082516060810184529054938416815260ff740100000000000000000000000000000000000000008504811692820192909252750100000000000000000000000000000000000000000090930416151590820181905290915061159b578282815181106115445761154461595d565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401611156565b60006115e8601283602001518686815181106115b9576115b961595d565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16613484565b9050600660008585815181106116005761160061595d565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff168484815181106116725761167261595d565b60200260200101516040015163ffffffff16101561169157505061183f565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018585815181106116d2576116d261595d565b60200260200101516040015163ffffffff16815250600660008686815181106116fd576116fd61595d565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905583518490849081106117955761179561595d565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a828686815181106117eb576117eb61595d565b6020026020010151604001516040516118349291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a250505b60010161147f565b505050505050505050565b61185a612133565b61132181613547565b61186b612133565b611321816136d3565b6060610d30600b6120e1565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169183018290527f000000000000000000000000000000000000000000000000000000000000000016906119429042615adf565b101561194e5792915050565b73ffffffffffffffffffffffffffffffffffffffff80841660009081526007602090815260409182902082516060810184529054938416815260ff74010000000000000000000000000000000000000000850481169282019290925275010000000000000000000000000000000000000000009093041615801591830191909152806119ef5750805173ffffffffffffffffffffffffffffffffffffffff16155b156119fb575092915050565b6000611a06826137bd565b9050826020015163ffffffff16816020015163ffffffff161015611a2a5782611a2c565b805b95945050505050565b67ffffffffffffffff8083166000908152600960209081526040808320815161022081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a0860152710100000000000000000000000000000000008404871660c08601527501000000000000000000000000000000000000000000808504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c01000000000000000000000000880485166101a084015270010000000000000000000000000000000088049094166101c083015274010000000000000000000000000000000000000000870490931615156101e08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b16610200840152909190611c6f576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401611156565b611c8a611c8260808501606086016145ef565b600b9061394f565b611ce957611c9e60808401606085016145ef565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401611156565b6000611cf860408501856158f5565b9150611d54905082611d0d6020870187615af2565b905083611d1a8880615af2565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061397e92505050565b6000611d6e611d6960808701606088016145ef565b612047565b90506000611d8187856101c00151613a3b565b9050600080808515611dc157611db5878b611da260808d0160608e016145ef565b88611db060408f018f6158f5565b613b3b565b91945092509050611de1565b6101a0870151611dde9063ffffffff16662386f26fc100006158a3565b92505b61010087015160009061ffff1615611e2557611e22886dffffffffffffffffffffffffffff607088901c16611e1960208e018e615af2565b90508a86613e13565b90505b61018088015160009067ffffffffffffffff16611e4e611e4860808e018e615af2565b8c613ec3565b600001518563ffffffff168b60a0015161ffff168e8060200190611e729190615af2565b611e7d9291506158a3565b8c6080015163ffffffff16611e929190615b57565b611e9c9190615b57565b611ea69190615b57565b611ec0906dffffffffffffffffffffffffffff89166158a3565b611eca91906158a3565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f6060016020810190611f0491906145ef565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054611f3f9067ffffffffffffffff16896158a3565b611f499190615b57565b611f539190615b57565b611f5d91906158ba565b9c9b505050505050505050505050565b611f75612133565b61132181613f84565b611f86612133565b61132181614048565b67ffffffffffffffff8116600090815260096020526040812054819060ff16611ff0576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401611156565b611ff984612047565b67ffffffffffffffff841660009081526009602052604090206001015461203b908590700100000000000000000000000000000000900463ffffffff16613a3b565b915091505b9250929050565b60008061205383611880565b9050806020015163ffffffff166000148061208b575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b156120da576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401611156565b5192915050565b60606000610bec8361419a565b6120f960023361394f565b612131576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401611156565b565b60015473ffffffffffffffffffffffffffffffffffffffff163314612131576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061223d82600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a39061234a908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b6040805180820190915260008082526020820152600083900361239757506040805180820190915267ffffffffffffffff8216815260006020820152610bec565b60006123a38486615b6a565b905060006123b48560048189615bb0565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f0000000000000000000000000000000000000000000000000000000000161245157808060200190518101906124489190615bda565b92505050610bec565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016124cd576040518060400160405280828060200190518101906124b99190615c06565b815260006020909101529250610bec915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff808616600090815260096020526040902060010154606091750100000000000000000000000000000000000000000090910460e01b90859081111561254f5761254f614716565b60405190808252806020026020018201604052801561258257816020015b606081526020019060019003908161256d5790505b50915060005b858110156128775760008585838181106125a4576125a461595d565b6125ba92602060409092020190810191506145ef565b905060008888848181106125d0576125d061595d565b90506020028101906125e29190615c1f565b6125f0906040810190615af2565b91505060208111156126a05767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff168111156126a0576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401611156565b612710848a8a868181106126b6576126b661595d565b90506020028101906126c89190615c1f565b6126d6906020810190615af2565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141f692505050565b67ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684528252808320815160c081018352905463ffffffff8082168352640100000000820481169483019490945268010000000000000000810461ffff16928201929092526a01000000000000000000008204831660608201526e010000000000000000000000000000820490921660808301527201000000000000000000000000000000000000900460ff16151560a082018190529091906128225767ffffffffffffffff8c166000908152600960205260409020547b01000000000000000000000000000000000000000000000000000000900463ffffffff16612828565b81606001515b6040805163ffffffff831660208201529192500160405160208183030381529060405287868151811061285d5761285d61595d565b602002602001018190525050505050806001019050612588565b505095945050505050565b60005b81518110156110285760008282815181106128a2576128a261595d565b6020026020010151905060008383815181106128c0576128c061595d565b60200260200101516000015190506000826020015190508167ffffffffffffffff16600014806128f9575061016081015163ffffffff16155b8061294b57506102008101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b8061296a5750806060015163ffffffff1681610160015163ffffffff16115b156129ad576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401611156565b67ffffffffffffffff82166000908152600960205260408120600101547501000000000000000000000000000000000000000000900460e01b7fffffffff00000000000000000000000000000000000000000000000000000000169003612a55578167ffffffffffffffff167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda4626582604051612a489190614f5e565b60405180910390a2612a98565b8167ffffffffffffffff167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a83582604051612a8f9190614f5e565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050612885565b60005b82518110156130e1576000838281518110612d7457612d7461595d565b6020026020010151905060008160000151905060005b8260200151518110156130d357600083602001518281518110612daf57612daf61595d565b6020026020010151602001519050600084602001518381518110612dd557612dd561595d565b6020026020010151600001519050816020015163ffffffff16826000015163ffffffff1610612e4757815160208301516040517f0b4f67a200000000000000000000000000000000000000000000000000000000815263ffffffff928316600482015291166024820152604401611156565b602063ffffffff16826080015163ffffffff161015612ebc5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401611156565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906130c1908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612d8a565b505050806001019050612d57565b5060005b81518110156131c55760008282815181106131025761310261595d565b602002602001015160000151905060008383815181106131245761312461595d565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a350506001016130e5565b505050565b60005b825181101561326d576132038382815181106131eb576131eb61595d565b6020026020010151600b61424890919063ffffffff16565b156132655782818151811061321a5761321a61595d565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6001016131cd565b5060005b81518110156131c5576132a782828151811061328f5761328f61595d565b6020026020010151600b61426a90919063ffffffff16565b15613309578181815181106132be576132be61595d565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101613271565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff1661347d576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401611156565b5050505050565b6000806134918486615c5d565b9050600060248260ff1611156134cb576134af602460ff8416615adf565b6134ba90600a615d96565b6134c490856158ba565b90506134f1565b6134d960ff83166024615adf565b6134e490600a615d96565b6134ee90856158a3565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115611a2c576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160005b81518110156135e257600082828151811061356c5761356c61595d565b6020026020010151905061358a81600261428c90919063ffffffff16565b156135d95760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010161354f565b50815160005b8151811015610fe45760008282815181106136055761360561595d565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613675576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61368060028261426a565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a1506001016135e8565b60005b81518110156110285760008282815181106136f3576136f361595d565b602002602001015160000151905060008383815181106137155761371561595d565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a250506001016136d6565b60408051808201909152600080825260208201526000826000015190506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061384c9190615dbc565b50935050925050600082121561388e576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061390d8473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139029190615e0c565b876020015185613484565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff909216602083015250949350505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610bec565b836040015163ffffffff168311156139d75760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401611156565b836020015161ffff16821115613a2c5760208401516040517fd88dddd60000000000000000000000000000000000000000000000000000000081526004810184905261ffff9091166024820152604401611156565b610fe4846102000151826141f6565b67ffffffffffffffff821660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116825263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169282019290925290831615613b33576000816020015163ffffffff1642613ad09190615adf565b90508363ffffffff16811115613b31576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff8516602482015260448101829052606401611156565b505b519392505050565b6000808083815b81811015613e05576000878783818110613b5e57613b5e61595d565b905060400201803603810190613b749190615e29565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613c94576101208d0151613c619061ffff16662386f26fc100006158a3565b613c6b9088615b57565b96508c610140015186613c7e9190615e62565b9550613c8b602086615e62565b94505050613dfd565b604081015160009061ffff1615613d4d5760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613cf0578351613ce990612047565b9050613cf3565b508a5b620186a0836040015161ffff16613d358660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166142ae90919063ffffffff16565b613d3f91906158a3565b613d4991906158ba565b9150505b6060820151613d5c9088615e62565b9650816080015186613d6e9190615e62565b8251909650600090613d8d9063ffffffff16662386f26fc100006158a3565b905080821015613dac57613da1818a615b57565b985050505050613dfd565b6000836020015163ffffffff16662386f26fc10000613dcb91906158a3565b905080831115613deb57613ddf818b615b57565b99505050505050613dfd565b613df5838b615b57565b995050505050505b600101613b42565b505096509650969350505050565b60008063ffffffff8316613e29610120866158a3565b613e35876101e0615b57565b613e3f9190615b57565b613e499190615b57565b905060008760c0015163ffffffff168860e0015161ffff1683613e6c91906158a3565b613e769190615b57565b61010089015190915061ffff16613e9d6dffffffffffffffffffffffffffff8916836158a3565b613ea791906158a3565b613eb790655af3107a40006158a3565b98975050505050505050565b60408051808201909152600080825260208201526000613eef858585610160015163ffffffff16612356565b9050826060015163ffffffff1681600001511115613f39576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015613f4d57508060200151155b15610be9576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613fd3576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b81518110156110285760008282815181106140685761406861595d565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a0180518589018051949098167fffffffffffffffffffffff00000000000000000000000000000000000000000090931683177401000000000000000000000000000000000000000060ff92831602177fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000009415159490940293909317909355835190815291511697810197909752915115159186019190915292945090929091907fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf9060600160405180910390a250505080600101905061404b565b6060816000018054806020026020016040519081016040528092919081815260200182805480156141ea57602002820191906000526020600020905b8154815260200190600101908083116141d6575b50505050509050919050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601611028576131c5816142eb565b6000610bec8373ffffffffffffffffffffffffffffffffffffffff841661439e565b6000610bec8373ffffffffffffffffffffffffffffffffffffffff8416614498565b6000610bec8373ffffffffffffffffffffffffffffffffffffffff84166144e7565b6000670de0b6b3a76400006142e1837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166158a3565b610bec91906158ba565b6000815160201461432a57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401611156919061466e565b6000828060200190518101906143409190615c06565b905073ffffffffffffffffffffffffffffffffffffffff811180614365575061040081105b15610d1e57826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401611156919061466e565b600081815260018301602052604081205480156144875760006143c2600183615adf565b85549091506000906143d690600190615adf565b905080821461443b5760008660000182815481106143f6576143f661595d565b90600052602060002001549050808760000184815481106144195761441961595d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061444c5761444c615e7f565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d1e565b6000915050610d1e565b5092915050565b60008181526001830160205260408120546144df57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d1e565b506000610d1e565b6000818152600183016020526040812054801561448757600061450b600183615adf565b855490915060009061451f90600190615adf565b905081811461443b5760008660000182815481106143f6576143f661595d565b803573ffffffffffffffffffffffffffffffffffffffff8116811461456357600080fd5b919050565b60008060006060848603121561457d57600080fd5b6145868461453f565b92506020840135915061459b6040850161453f565b90509250925092565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461456357600080fd5b6000602082840312156145e657600080fd5b610bec826145a4565b60006020828403121561460157600080fd5b610bec8261453f565b6000815180845260005b8181101561463057602081850181015186830182015201614614565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610bec602083018461460a565b6020808252825182820181905260009190848201906040850190845b818110156146cf57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161469d565b50909695505050505050565b6000602082840312156146ed57600080fd5b813567ffffffffffffffff81111561470457600080fd5b820160408185031215610bec57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561476857614768614716565b60405290565b6040805190810167ffffffffffffffff8111828210171561476857614768614716565b604051610220810167ffffffffffffffff8111828210171561476857614768614716565b60405160c0810167ffffffffffffffff8111828210171561476857614768614716565b6040516060810167ffffffffffffffff8111828210171561476857614768614716565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561484257614842614716565b604052919050565b600067ffffffffffffffff82111561486457614864614716565b5060051b60200190565b801515811461132157600080fd5b80356145638161486e565b6000602080838503121561489a57600080fd5b823567ffffffffffffffff8111156148b157600080fd5b8301601f810185136148c257600080fd5b80356148d56148d08261484a565b6147fb565b81815260a091820283018401918482019190888411156148f457600080fd5b938501935b838510156149c75780858a0312156149115760008081fd5b614919614745565b6149228661453f565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146149575760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146149905760008081fd5b9082015260606149a187820161453f565b908201526080868101356149b48161486e565b90820152835293840193918501916148f9565b50979650505050505050565b803567ffffffffffffffff8116811461456357600080fd5b60008083601f8401126149fd57600080fd5b50813567ffffffffffffffff811115614a1557600080fd5b60208301915083602082850101111561204057600080fd5b60008083601f840112614a3f57600080fd5b50813567ffffffffffffffff811115614a5757600080fd5b6020830191508360208260051b850101111561204057600080fd5b600080600080600080600080600060c08a8c031215614a9057600080fd5b614a998a6149d3565b9850614aa760208b0161453f565b975060408a0135965060608a013567ffffffffffffffff80821115614acb57600080fd5b614ad78d838e016149eb565b909850965060808c0135915080821115614af057600080fd5b614afc8d838e01614a2d565b909650945060a08c0135915080821115614b1557600080fd5b818c0191508c601f830112614b2957600080fd5b813581811115614b3857600080fd5b8d60208260061b8501011115614b4d57600080fd5b6020830194508093505050509295985092959850929598565b848152600060208515158184015260806040840152614b88608084018661460a565b8381036060850152845180825282820190600581901b8301840184880160005b83811015614bf4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552614be283835161460a565b94870194925090860190600101614ba8565b50909b9a5050505050505050505050565b60008060208385031215614c1857600080fd5b823567ffffffffffffffff811115614c2f57600080fd5b614c3b85828601614a2d565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614cb557614ca584835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614c64565b5091979650505050505050565b600060208284031215614cd457600080fd5b610bec826149d3565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff169082015260408101610d1e565b803561ffff8116811461456357600080fd5b803563ffffffff8116811461456357600080fd5b60006020808385031215614d5157600080fd5b823567ffffffffffffffff811115614d6857600080fd5b8301601f81018513614d7957600080fd5b8035614d876148d08261484a565b8181526102409182028301840191848201919088841115614da757600080fd5b938501935b838510156149c75784890381811215614dc55760008081fd5b614dcd61476e565b614dd6876149d3565b8152610220807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084011215614e0b5760008081fd5b614e13614791565b9250614e2089890161487c565b83526040614e2f818a01614d18565b8a8501526060614e40818b01614d2a565b8286015260809150614e53828b01614d2a565b9085015260a0614e648a8201614d2a565b8286015260c09150614e77828b01614d18565b9085015260e0614e888a8201614d2a565b828601526101009150614e9c828b01614d18565b90850152610120614eae8a8201614d18565b828601526101409150614ec2828b01614d18565b90850152610160614ed48a8201614d2a565b828601526101809150614ee8828b01614d2a565b908501526101a0614efa8a82016149d3565b828601526101c09150614f0e828b01614d2a565b908501526101e0614f208a8201614d2a565b828601526102009150614f34828b0161487c565b90850152614f438983016145a4565b90840152508088019190915283529384019391850191614dac565b81511515815261022081016020830151614f7e602084018261ffff169052565b506040830151614f96604084018263ffffffff169052565b506060830151614fae606084018263ffffffff169052565b506080830151614fc6608084018263ffffffff169052565b5060a0830151614fdc60a084018261ffff169052565b5060c0830151614ff460c084018263ffffffff169052565b5060e083015161500a60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b600082601f8301126150d557600080fd5b813560206150e56148d08361484a565b82815260069290921b8401810191818101908684111561510457600080fd5b8286015b8481101561515157604081890312156151215760008081fd5b61512961476e565b615132826149d3565b815261513f85830161453f565b81860152835291830191604001615108565b509695505050505050565b6000806040838503121561516f57600080fd5b67ffffffffffffffff8335111561518557600080fd5b83601f84358501011261519757600080fd5b6151a76148d0843585013561484a565b8335840180358083526020808401939260059290921b909101018610156151cd57600080fd5b602085358601015b85358601803560051b016020018110156153da5767ffffffffffffffff813511156151ff57600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a0301121561523857600080fd5b61524061476e565b61524c602083016149d3565b815267ffffffffffffffff6040830135111561526757600080fd5b88603f60408401358401011261527c57600080fd5b6152926148d0602060408501358501013561484a565b6020604084810135850182810135808552928401939260e00201018b10156152b957600080fd5b6040808501358501015b6040858101358601602081013560e00201018110156153bb5760e0818d0312156152ec57600080fd5b6152f461476e565b6152fd8261453f565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f0301121561533157600080fd5b6153396147b5565b61534560208401614d2a565b815261535360408401614d2a565b602082015261536460608401614d18565b604082015261537560808401614d2a565b606082015261538660a08401614d2a565b608082015261539860c084013561486e565b60c083013560a0820152602082810191909152908452929092019160e0016152c3565b50806020840152505080855250506020830192506020810190506151d5565b5092505067ffffffffffffffff602084013511156153f757600080fd5b61540784602085013585016150c4565b90509250929050565b600082601f83011261542157600080fd5b813560206154316148d08361484a565b8083825260208201915060208460051b87010193508684111561545357600080fd5b602086015b84811015615151576154698161453f565b8352918301918301615458565b6000806040838503121561548957600080fd5b823567ffffffffffffffff808211156154a157600080fd5b6154ad86838701615410565b935060208501359150808211156154c357600080fd5b506154d085828601615410565b9150509250929050565b600080600080604085870312156154f057600080fd5b843567ffffffffffffffff8082111561550857600080fd5b615514888389016149eb565b9096509450602087013591508082111561552d57600080fd5b5061553a878288016149eb565b95989497509550505050565b6000806040838503121561555957600080fd5b615562836149d3565b91506154076020840161453f565b60006020828403121561558257600080fd5b813567ffffffffffffffff8082111561559a57600080fd5b90830190604082860312156155ae57600080fd5b6155b661476e565b8235828111156155c557600080fd5b6155d187828601615410565b8252506020830135828111156155e657600080fd5b6155f287828601615410565b60208301525095945050505050565b6000602080838503121561561457600080fd5b823567ffffffffffffffff81111561562b57600080fd5b8301601f8101851361563c57600080fd5b803561564a6148d08261484a565b81815260069190911b8201830190838101908783111561566957600080fd5b928401925b828410156156bb57604084890312156156875760008081fd5b61568f61476e565b6156988561453f565b81526156a58686016149d3565b818701528252604093909301929084019061566e565b979650505050505050565b600080604083850312156156d957600080fd5b6156e2836149d3565b9150602083013567ffffffffffffffff8111156156fe57600080fd5b830160a0818603121561571057600080fd5b809150509250929050565b60ff8116811461132157600080fd5b6000602080838503121561573d57600080fd5b823567ffffffffffffffff81111561575457600080fd5b8301601f8101851361576557600080fd5b80356157736148d08261484a565b81815260079190911b8201830190838101908783111561579257600080fd5b928401925b828410156156bb5783880360808112156157b15760008081fd5b6157b961476e565b6157c28661453f565b81526060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156157f65760008081fd5b6157fe6147d8565b925061580b88880161453f565b835260408088013561581c8161571b565b848a0152908701359061582e8261486e565b8301528087019190915282526080939093019290840190615797565b6000806040838503121561585d57600080fd5b6158668361453f565b9150615407602084016149d3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610d1e57610d1e615874565b6000826158f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261592a57600080fd5b83018035915067ffffffffffffffff82111561594557600080fd5b6020019150600681901b360382131561204057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461456357600080fd5b6000604082840312156159ca57600080fd5b6159d261476e565b6159db8361453f565b81526159e96020840161598c565b60208201529392505050565b600060408284031215615a0757600080fd5b615a0f61476e565b6159db836149d3565b60006020808385031215615a2b57600080fd5b823567ffffffffffffffff811115615a4257600080fd5b8301601f81018513615a5357600080fd5b8035615a616148d08261484a565b81815260609182028301840191848201919088841115615a8057600080fd5b938501935b838510156149c75780858a031215615a9d5760008081fd5b615aa56147d8565b615aae8661453f565b8152615abb87870161598c565b878201526040615acc818801614d2a565b9082015283529384019391850191615a85565b81810381811115610d1e57610d1e615874565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615b2757600080fd5b83018035915067ffffffffffffffff821115615b4257600080fd5b60200191503681900382131561204057600080fd5b80820180821115610d1e57610d1e615874565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156150bc5760049490940360031b84901b1690921692915050565b60008085851115615bc057600080fd5b83861115615bcd57600080fd5b5050820193919092039150565b600060408284031215615bec57600080fd5b615bf461476e565b8251815260208301516159e98161486e565b600060208284031215615c1857600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112615c5357600080fd5b9190910192915050565b60ff8181168382160190811115610d1e57610d1e615874565b600181815b80851115615ccf57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615cb557615cb5615874565b80851615615cc257918102915b93841c9390800290615c7b565b509250929050565b600082615ce657506001610d1e565b81615cf357506000610d1e565b8160018114615d095760028114615d1357615d2f565b6001915050610d1e565b60ff841115615d2457615d24615874565b50506001821b610d1e565b5060208310610133831016604e8410600b8410161715615d52575081810a610d1e565b615d5c8383615c76565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615d8e57615d8e615874565b029392505050565b6000610bec8383615cd7565b805169ffffffffffffffffffff8116811461456357600080fd5b600080600080600060a08688031215615dd457600080fd5b615ddd86615da2565b9450602086015193506040860151925060608601519150615e0060808701615da2565b90509295509295909350565b600060208284031215615e1e57600080fd5b8151610bec8161571b565b600060408284031215615e3b57600080fd5b615e4361476e565b615e4c8361453f565b8152602083013560208201528091505092915050565b63ffffffff81811683821601908082111561449157614491615874565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var FeeQuoterABI = FeeQuoterMetaData.ABI @@ -710,6 +710,28 @@ func (_FeeQuoter *FeeQuoterCallerSession) ProcessMessageArgs(destChainSelector u return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) } +func (_FeeQuoter *FeeQuoterCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _FeeQuoter.Contract.SupportsInterface(&_FeeQuoter.CallOpts, interfaceId) +} + +func (_FeeQuoter *FeeQuoterCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _FeeQuoter.Contract.SupportsInterface(&_FeeQuoter.CallOpts, interfaceId) +} + func (_FeeQuoter *FeeQuoterCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { var out []interface{} err := _FeeQuoter.contract.Call(opts, &out, "typeAndVersion") @@ -2949,6 +2971,8 @@ type FeeQuoterInterface interface { error) + SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) + TypeAndVersion(opts *bind.CallOpts) (string, error) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go b/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go index 044c75b8b40..32edf6ef6c3 100644 --- a/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go +++ b/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go @@ -81,8 +81,8 @@ type TokenPoolChainUpdate struct { } var LockReleaseTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"acceptLiquidity\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLiquidity\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"canAcceptLiquidity\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRebalancer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"provideLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rebalancer\",\"type\":\"address\"}],\"name\":\"setRebalancer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162004f2338038062004f23833981016040819052620000359162000509565b8585858584336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000153565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0385811660805282811660c05260ff851660a052600480546001600160a01b031916918316919091179055825115801560e0526200013b576040805160008152602081019091526200013b9084620001cd565b50505050911515610100525062000693945050505050565b336001600160a01b038216036200017d57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e051620001ee576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200027957600083828151811062000212576200021262000645565b602090810291909101015190506200022c6002826200032a565b156200026f576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620001f1565b5060005b8151811015620003255760008282815181106200029e576200029e62000645565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002ca57506200031c565b620002d76002826200034a565b156200031a576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b6001016200027d565b505050565b600062000341836001600160a01b03841662000361565b90505b92915050565b600062000341836001600160a01b03841662000465565b600081815260018301602052604081205480156200045a576000620003886001836200065b565b85549091506000906200039e906001906200065b565b90508082146200040a576000866000018281548110620003c257620003c262000645565b9060005260206000200154905080876000018481548110620003e857620003e862000645565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200041e576200041e6200067d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000344565b600091505062000344565b6000818152600183016020526040812054620004ae5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000344565b50600062000344565b6001600160a01b0381168114620004cd57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620004f381620004b7565b919050565b80518015158114620004f357600080fd5b60008060008060008060c087890312156200052357600080fd5b86516200053081620004b7565b8096505060208088015160ff811681146200054a57600080fd5b60408901519096506001600160401b03808211156200056857600080fd5b818a0191508a601f8301126200057d57600080fd5b815181811115620005925762000592620004d0565b8060051b604051601f19603f83011681018181108582111715620005ba57620005ba620004d0565b60405291825284820192508381018501918d831115620005d957600080fd5b938501935b828510156200060257620005f285620004e6565b84529385019392850192620005de565b8099505050505050506200061960608801620004e6565b92506200062960808801620004f8565b91506200063960a08801620004e6565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b818103818111156200034457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e051610100516147cd62000756600039600081816105a40152611ac601526000818161063e015281816121f10152612d0a01526000818161061801528181611e3501526124dd01526000818161036701528181610e6b01528181611fde01528181612098015281816120cc015281816120fd01526121440152600081816102ce015281816103230152818161077f015281816108510152818161094501528181611b8801528181612ca00152612ef501526147cd6000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80638da5cb5b11610145578063c0d78655116100bd578063dc0bd9711161008c578063e8a1da1711610071578063e8a1da1714610662578063eb521a4c14610675578063f2fde38b1461068857600080fd5b8063dc0bd97114610616578063e0351e131461063c57600080fd5b8063c0d78655146105c8578063c4bffe2b146105db578063c75eea9c146105f0578063cf7401f31461060357600080fd5b8063acfecf9111610114578063b0f479a1116100f9578063b0f479a114610571578063b79465801461058f578063bb98546b146105a257600080fd5b8063acfecf91146104ef578063af58d59f1461050257600080fd5b80638da5cb5b1461047c5780639a4575b91461049a578063a42a7b8b146104ba578063a7cd63b7146104da57600080fd5b80634c5ef0ed116101d85780636cfd1553116101a757806379ba50971161018c57806379ba50971461044e5780637d54534e146104565780638926f54f1461046957600080fd5b80636cfd15531461041d5780636d3d1a581461043057600080fd5b80634c5ef0ed146103d157806354c8a4f3146103e457806362ddd3c4146103f7578063663200871461040a57600080fd5b8063240028e811610214578063240028e81461031357806324f65ee7146103605780633907753714610391578063432a6ba3146103b357600080fd5b806301ffc9a7146102465780630a861f2a1461026e578063181f5a771461028357806321df0da7146102cc575b600080fd5b6102596102543660046138bc565b61069b565b60405190151581526020015b60405180910390f35b61028161027c3660046138fe565b6106f7565b005b6102bf6040518060400160405280601a81526020017f4c6f636b52656c65617365546f6b656e506f6f6c20312e352e3100000000000081525081565b6040516102659190613985565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610265565b6102596103213660046139ba565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610265565b6103a461039f3660046139d7565b6108a8565b60405190518152602001610265565b600a5473ffffffffffffffffffffffffffffffffffffffff166102ee565b6102596103df366004613a30565b6109f6565b6102816103f2366004613aff565b610a40565b610281610405366004613a30565b610abb565b610281610418366004613b6b565b610b53565b61028161042b3660046139ba565b610c2f565b60095473ffffffffffffffffffffffffffffffffffffffff166102ee565b610281610c7e565b6102816104643660046139ba565b610d4c565b610259610477366004613b97565b610dcd565b60015473ffffffffffffffffffffffffffffffffffffffff166102ee565b6104ad6104a8366004613bb2565b610de4565b6040516102659190613bed565b6104cd6104c8366004613b97565b610eb0565b6040516102659190613c44565b6104e261101b565b6040516102659190613cc6565b6102816104fd366004613a30565b61102c565b610515610510366004613b97565b611144565b604051610265919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102ee565b6102bf61059d366004613b97565b611219565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b6102816105d63660046139ba565b6112c9565b6105e36113a4565b6040516102659190613d20565b6105156105fe366004613b97565b61145c565b610281610611366004613ea8565b61152e565b7f00000000000000000000000000000000000000000000000000000000000000006102ee565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b610281610670366004613aff565b6115b2565b6102816106833660046138fe565b611ac4565b6102816106963660046139ba565b611be0565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe1d405660000000000000000000000000000000000000000000000000000000014806106f157506106f182611bf4565b92915050565b600a5473ffffffffffffffffffffffffffffffffffffffff16331461074f576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156107db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ff9190613eed565b1015610837576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61087873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611cd8565b604051819033907fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf984017171990600090a350565b6040805160208101909152600081526108c082611dac565b600061091960608401356109146108da60c0870187613f06565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611fd092505050565b612094565b905061096c61092e60608501604086016139ba565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169083611cd8565b61097c60608401604085016139ba565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52836040516109da91815260200190565b60405180910390a3604080516020810190915290815292915050565b6000610a388383604051610a0b929190613f6b565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190612184565b949350505050565b610a4861219c565b610ab5848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284376000920191909152506121ef92505050565b50505050565b610ac361219c565b610acc83610dcd565b610b0e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610746565b610b4e8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506123a592505050565b505050565b610b5b61219c565b6040517f0a861f2a0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff831690630a861f2a90602401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db6282604051610c2391815260200190565b60405180910390a25050565b610c3761219c565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ccf576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610d5461219c565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006106f1600567ffffffffffffffff8416612184565b6040805180820190915260608082526020820152610e018261249f565b6040516060830135815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a26040518060400160405280610e5b84602001602081019061059d9190613b97565b8152602001610ea86040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610ed99060050161262b565b90506000815167ffffffffffffffff811115610ef757610ef7613d62565b604051908082528060200260200182016040528015610f2a57816020015b6060815260200190600190039081610f155790505b50905060005b82518110156110135760086000848381518110610f4f57610f4f613f7b565b602002602001015181526020019081526020016000208054610f7090613faa565b80601f0160208091040260200160405190810160405280929190818152602001828054610f9c90613faa565b8015610fe95780601f10610fbe57610100808354040283529160200191610fe9565b820191906000526020600020905b815481529060010190602001808311610fcc57829003601f168201915b505050505082828151811061100057611000613f7b565b6020908102919091010152600101610f30565b509392505050565b6060611027600261262b565b905090565b61103461219c565b61103d83610dcd565b61107f576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610746565b6110bf8282604051611092929190613f6b565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190612638565b6110fb578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161074693929190614046565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76838360405161113792919061406a565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526106f190612644565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061124490613faa565b80601f016020809104026020016040519081016040528092919081815260200182805461127090613faa565b80156112bd5780601f10611292576101008083540402835291602001916112bd565b820191906000526020600020905b8154815290600101906020018083116112a057829003601f168201915b50505050509050919050565b6112d161219c565b73ffffffffffffffffffffffffffffffffffffffff811661131e576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006113b2600561262b565b90506000815167ffffffffffffffff8111156113d0576113d0613d62565b6040519080825280602002602001820160405280156113f9578160200160208202803683370190505b50905060005b82518110156114555782818151811061141a5761141a613f7b565b602002602001015182828151811061143457611434613f7b565b67ffffffffffffffff909216602092830291909101909101526001016113ff565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526106f190612644565b60095473ffffffffffffffffffffffffffffffffffffffff16331480159061156e575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156115a7576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b610b4e8383836126f6565b6115ba61219c565b60005b838110156117a75760008585838181106115d9576115d9613f7b565b90506020020160208101906115ee9190613b97565b9050611605600567ffffffffffffffff8316612638565b611647576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610746565b67ffffffffffffffff8116600090815260076020526040812061166c9060050161262b565b905060005b81518110156116d8576116cf82828151811061168f5761168f613f7b565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161263890919063ffffffff16565b50600101611671565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611741600483018261384f565b60058201600081816117538282613889565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991694506020019250611795915050565b60405180910390a150506001016115bd565b5060005b81811015611abd5760008383838181106117c7576117c7613f7b565b90506020028101906117d9919061407e565b6117e29061414a565b90506117f3816060015160006127e0565b611802816080015160006127e0565b806040015151600003611841576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516118599060059067ffffffffffffffff1661291d565b61189e5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610746565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a909102999093161717909416959095179092559092029091176003820155908201516004820190611a2190826142c1565b5060005b826020015151811015611a6557611a5d836000015184602001518381518110611a5057611a50613f7b565b60200260200101516123a5565b600101611a25565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c28260000151836040015184606001518560800151604051611aab94939291906143db565b60405180910390a150506001016117ab565b5050505050565b7f0000000000000000000000000000000000000000000000000000000000000000611b1b576040517fe93f8fa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a5473ffffffffffffffffffffffffffffffffffffffff163314611b6e576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b611bb073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612929565b604051819033907fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb31208890600090a350565b611be861219c565b611bf181612987565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf000000000000000000000000000000000000000000000000000000001480611c8757507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806106f157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610b4e9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a4b565b611dbf61032160a08301608084016139ba565b611e1e57611dd360a08201608083016139ba565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610746565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611e6a6040840160208501613b97565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff9190614474565b15611f36576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611f4e611f496040830160208401613b97565b612b57565b611f6e611f616040830160208401613b97565b6103df60a0840184613f06565b611fb357611f7f60a0820182613f06565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161074692919061406a565b611bf1611fc66040830160208401613b97565b8260600135612c7d565b6000815160000361200257507f0000000000000000000000000000000000000000000000000000000000000000919050565b815160201461203f57816040517f953576f70000000000000000000000000000000000000000000000000000000081526004016107469190613985565b6000828060200190518101906120559190613eed565b905060ff8111156106f157826040517f953576f70000000000000000000000000000000000000000000000000000000081526004016107469190613985565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff16036120ca5750816106f1565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff16111561213e576121227f0000000000000000000000000000000000000000000000000000000000000000836144c0565b61212d90600a6145f9565b6121379084614608565b90506106f1565b612168827f00000000000000000000000000000000000000000000000000000000000000006144c0565b61217390600a6145f9565b61217d9084614643565b9392505050565b6000818152600183016020526040812054151561217d565b60015473ffffffffffffffffffffffffffffffffffffffff1633146121ed576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000612246576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82518110156122dc57600083828151811061226657612266613f7b565b60200260200101519050612284816002612cc490919063ffffffff16565b156122d35760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101612249565b5060005b8151811015610b4e5760008282815181106122fd576122fd613f7b565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612341575061239d565b61234c600282612ce6565b1561239b5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b6001016122e0565b80516000036123e0576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120612412906005018261291d565b61244c5782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161074692919061465a565b600081815260086020526040902061246483826142c1565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea836040516111379190613985565b6124b261032160a08301608084016139ba565b6124c657611dd360a08201608083016139ba565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6125126040840160208501613b97565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612583573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a79190614474565b156125de576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6125f66125f160608301604084016139ba565b612d08565b61260e6126096040830160208401613b97565b612d87565b611bf16126216040830160208401613b97565b8260600135612ed5565b6060600061217d83612f19565b600061217d8383612f74565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526126d282606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426126b6919061467d565b85608001516fffffffffffffffffffffffffffffffff16613067565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b6126ff83610dcd565b612741576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610746565b61274c8260006127e0565b67ffffffffffffffff8316600090815260076020526040902061276f908361308f565b61277a8160006127e0565b67ffffffffffffffff831660009081526007602052604090206127a0906002018261308f565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516127d393929190614690565b60405180910390a1505050565b8151156128ab5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612836575060408201516fffffffffffffffffffffffffffffffff16155b1561286f57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016107469190614713565b80156128a7576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff161515806128e4575060208201516fffffffffffffffffffffffffffffffff1615155b156128a757816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016107469190614713565b600061217d8383613231565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610ab59085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611d2a565b3373ffffffffffffffffffffffffffffffffffffffff8216036129d6576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000612aad826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166132809092919063ffffffff16565b805190915015610b4e5780806020019051810190612acb9190614474565b610b4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610746565b612b6081610dcd565b612ba2576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610746565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612c21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c459190614474565b611bf1576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b67ffffffffffffffff821660009081526007602052604090206128a790600201827f000000000000000000000000000000000000000000000000000000000000000061328f565b600061217d8373ffffffffffffffffffffffffffffffffffffffff8416612f74565b600061217d8373ffffffffffffffffffffffffffffffffffffffff8416613231565b7f000000000000000000000000000000000000000000000000000000000000000015611bf157612d39600282613612565b611bf1576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610746565b612d9081610dcd565b612dd2576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610746565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612e4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6f919061474f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611bf1576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b67ffffffffffffffff821660009081526007602052604090206128a790827f000000000000000000000000000000000000000000000000000000000000000061328f565b6060816000018054806020026020016040519081016040528092919081815260200182805480156112bd57602002820191906000526020600020905b815481526020019060010190808311612f555750505050509050919050565b6000818152600183016020526040812054801561305d576000612f9860018361467d565b8554909150600090612fac9060019061467d565b9050808214613011576000866000018281548110612fcc57612fcc613f7b565b9060005260206000200154905080876000018481548110612fef57612fef613f7b565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806130225761302261476c565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106f1565b60009150506106f1565b6000613086856130778486614643565b613081908761479b565b613641565b95945050505050565b81546000906130b890700100000000000000000000000000000000900463ffffffff164261467d565b9050801561315a5760018301548354613100916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416613067565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354613180916fffffffffffffffffffffffffffffffff9081169116613641565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906127d3908490614713565b6000818152600183016020526040812054613278575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106f1565b5060006106f1565b6060610a388484600085613657565b825474010000000000000000000000000000000000000000900460ff1615806132b6575081155b156132c057505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061330690700100000000000000000000000000000000900463ffffffff164261467d565b905080156133c65781831115613348576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546133829083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613067565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b8482101561347d5773ffffffffffffffffffffffffffffffffffffffff8416613425576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610746565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610746565b848310156135905760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906134c1908261467d565b6134cb878a61467d565b6134d5919061479b565b6134df9190614608565b905073ffffffffffffffffffffffffffffffffffffffff8616613538576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610746565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610746565b61359a858461467d565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561217d565b6000818310613650578161217d565b5090919050565b6060824710156136e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610746565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161371291906147ae565b60006040518083038185875af1925050503d806000811461374f576040519150601f19603f3d011682016040523d82523d6000602084013e613754565b606091505b509150915061376587838387613770565b979650505050505050565b606083156138065782516000036137ff5773ffffffffffffffffffffffffffffffffffffffff85163b6137ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610746565b5081610a38565b610a38838381511561381b5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107469190613985565b50805461385b90613faa565b6000825580601f1061386b575050565b601f016020900490600052602060002090810190611bf191906138a3565b5080546000825590600052602060002090810190611bf191905b5b808211156138b857600081556001016138a4565b5090565b6000602082840312156138ce57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461217d57600080fd5b60006020828403121561391057600080fd5b5035919050565b60005b8381101561393257818101518382015260200161391a565b50506000910152565b60008151808452613953816020860160208601613917565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061217d602083018461393b565b73ffffffffffffffffffffffffffffffffffffffff81168114611bf157600080fd5b6000602082840312156139cc57600080fd5b813561217d81613998565b6000602082840312156139e957600080fd5b813567ffffffffffffffff811115613a0057600080fd5b8201610100818503121561217d57600080fd5b803567ffffffffffffffff81168114613a2b57600080fd5b919050565b600080600060408486031215613a4557600080fd5b613a4e84613a13565b9250602084013567ffffffffffffffff80821115613a6b57600080fd5b818601915086601f830112613a7f57600080fd5b813581811115613a8e57600080fd5b876020828501011115613aa057600080fd5b6020830194508093505050509250925092565b60008083601f840112613ac557600080fd5b50813567ffffffffffffffff811115613add57600080fd5b6020830191508360208260051b8501011115613af857600080fd5b9250929050565b60008060008060408587031215613b1557600080fd5b843567ffffffffffffffff80821115613b2d57600080fd5b613b3988838901613ab3565b90965094506020870135915080821115613b5257600080fd5b50613b5f87828801613ab3565b95989497509550505050565b60008060408385031215613b7e57600080fd5b8235613b8981613998565b946020939093013593505050565b600060208284031215613ba957600080fd5b61217d82613a13565b600060208284031215613bc457600080fd5b813567ffffffffffffffff811115613bdb57600080fd5b820160a0818503121561217d57600080fd5b602081526000825160406020840152613c09606084018261393b565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152613086828261393b565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613cb9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613ca785835161393b565b94509285019290850190600101613c6d565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613d1457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613ce2565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613d1457835167ffffffffffffffff1683529284019291840191600101613d3c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613db457613db4613d62565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613e0157613e01613d62565b604052919050565b8015158114611bf157600080fd5b80356fffffffffffffffffffffffffffffffff81168114613a2b57600080fd5b600060608284031215613e4957600080fd5b6040516060810181811067ffffffffffffffff82111715613e6c57613e6c613d62565b6040529050808235613e7d81613e09565b8152613e8b60208401613e17565b6020820152613e9c60408401613e17565b60408201525092915050565b600080600060e08486031215613ebd57600080fd5b613ec684613a13565b9250613ed58560208601613e37565b9150613ee48560808601613e37565b90509250925092565b600060208284031215613eff57600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613f3b57600080fd5b83018035915067ffffffffffffffff821115613f5657600080fd5b602001915036819003821315613af857600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c90821680613fbe57607f821691505b602082108103613ff7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000613086604083018486613ffd565b602081526000610a38602083018486613ffd565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181126140b257600080fd5b9190910192915050565b600082601f8301126140cd57600080fd5b813567ffffffffffffffff8111156140e7576140e7613d62565b61411860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613dba565b81815284602083860101111561412d57600080fd5b816020850160208301376000918101602001919091529392505050565b6000610120823603121561415d57600080fd5b614165613d91565b61416e83613a13565b815260208084013567ffffffffffffffff8082111561418c57600080fd5b9085019036601f83011261419f57600080fd5b8135818111156141b1576141b1613d62565b8060051b6141c0858201613dba565b91825283810185019185810190368411156141da57600080fd5b86860192505b83831015614216578235858111156141f85760008081fd5b6142063689838a01016140bc565b83525091860191908601906141e0565b808789015250505050604086013592508083111561423357600080fd5b5050614241368286016140bc565b6040830152506142543660608501613e37565b60608201526142663660c08501613e37565b608082015292915050565b601f821115610b4e576000816000526020600020601f850160051c8101602086101561429a5750805b601f850160051c820191505b818110156142b9578281556001016142a6565b505050505050565b815167ffffffffffffffff8111156142db576142db613d62565b6142ef816142e98454613faa565b84614271565b602080601f831160018114614342576000841561430c5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556142b9565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561438f57888601518255948401946001909101908401614370565b50858210156143cb57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526143ff8184018761393b565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff908116606087015290870151166080850152915061443d9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152613086565b60006020828403121561448657600080fd5b815161217d81613e09565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff82811682821603908111156106f1576106f1614491565b600181815b8085111561453257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561451857614518614491565b8085161561452557918102915b93841c93908002906144de565b509250929050565b600082614549575060016106f1565b81614556575060006106f1565b816001811461456c576002811461457657614592565b60019150506106f1565b60ff84111561458757614587614491565b50506001821b6106f1565b5060208310610133831016604e8410600b84101617156145b5575081810a6106f1565b6145bf83836144d9565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156145f1576145f1614491565b029392505050565b600061217d60ff84168361453a565b60008261463e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176106f1576106f1614491565b67ffffffffffffffff83168152604060208201526000610a38604083018461393b565b818103818111156106f1576106f1614491565b67ffffffffffffffff8416815260e081016146dc60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610a38565b606081016106f182848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561476157600080fd5b815161217d81613998565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b808201808211156106f1576106f1614491565b600082516140b281846020870161391756fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"acceptLiquidity\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLiquidity\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"canAcceptLiquidity\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRebalancer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"provideLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rebalancer\",\"type\":\"address\"}],\"name\":\"setRebalancer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b506040516200511f3803806200511f8339810160408190526200003591620005bb565b8585858584336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f81620001f3565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e91810190620006ee565b60015b1562000191578060ff168560ff16146200018f576040516332ad3e0760e11b815260ff80871660048301528216602482015260440160405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001db57604080516000815260208101909152620001db90846200026d565b5050505091151561010052506200075a945050505050565b336001600160a01b038216036200021d57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e0516200028e576040516335f4a7b360e01b815260040160405180910390fd5b60005b825181101562000319576000838281518110620002b257620002b26200070c565b60209081029190910101519050620002cc600282620003ca565b156200030f576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000291565b5060005b8151811015620003c55760008282815181106200033e576200033e6200070c565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200036a5750620003bc565b62000377600282620003ea565b15620003ba576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b6001016200031d565b505050565b6000620003e1836001600160a01b03841662000401565b90505b92915050565b6000620003e1836001600160a01b03841662000505565b60008181526001830160205260408120548015620004fa5760006200042860018362000722565b85549091506000906200043e9060019062000722565b9050808214620004aa5760008660000182815481106200046257620004626200070c565b90600052602060002001549050808760000184815481106200048857620004886200070c565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004be57620004be62000744565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003e4565b6000915050620003e4565b60008181526001830160205260408120546200054e57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003e4565b506000620003e4565b6001600160a01b03811681146200056d57600080fd5b50565b805160ff811681146200058257600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620005828162000557565b805180151581146200058257600080fd5b60008060008060008060c08789031215620005d557600080fd5b8651620005e28162000557565b95506020620005f388820162000570565b60408901519096506001600160401b03808211156200061157600080fd5b818a0191508a601f8301126200062657600080fd5b8151818111156200063b576200063b62000587565b8060051b604051601f19603f8301168101818110858211171562000663576200066362000587565b60405291825284820192508381018501918d8311156200068257600080fd5b938501935b82851015620006ab576200069b856200059d565b8452938501939285019262000687565b809950505050505050620006c2606088016200059d565b9250620006d260808801620005aa565b9150620006e260a088016200059d565b90509295509295509295565b6000602082840312156200070157600080fd5b620003e18262000570565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003e457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e051610100516148f46200082b600039600081816105a40152611ac601526000818161063e015281816123180152612e3101526000818161061801528181611e35015261260401526000818161036701528181610e6b01528181611fde01528181612098015281816120cc015281816120ff01528181612164015281816121bd015261225f0152600081816102ce015281816103230152818161077f015281816108510152818161094501528181611b8801528181612dc7015261301c01526148f46000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80638da5cb5b11610145578063c0d78655116100bd578063dc0bd9711161008c578063e8a1da1711610071578063e8a1da1714610662578063eb521a4c14610675578063f2fde38b1461068857600080fd5b8063dc0bd97114610616578063e0351e131461063c57600080fd5b8063c0d78655146105c8578063c4bffe2b146105db578063c75eea9c146105f0578063cf7401f31461060357600080fd5b8063acfecf9111610114578063b0f479a1116100f9578063b0f479a114610571578063b79465801461058f578063bb98546b146105a257600080fd5b8063acfecf91146104ef578063af58d59f1461050257600080fd5b80638da5cb5b1461047c5780639a4575b91461049a578063a42a7b8b146104ba578063a7cd63b7146104da57600080fd5b80634c5ef0ed116101d85780636cfd1553116101a757806379ba50971161018c57806379ba50971461044e5780637d54534e146104565780638926f54f1461046957600080fd5b80636cfd15531461041d5780636d3d1a581461043057600080fd5b80634c5ef0ed146103d157806354c8a4f3146103e457806362ddd3c4146103f7578063663200871461040a57600080fd5b8063240028e811610214578063240028e81461031357806324f65ee7146103605780633907753714610391578063432a6ba3146103b357600080fd5b806301ffc9a7146102465780630a861f2a1461026e578063181f5a771461028357806321df0da7146102cc575b600080fd5b6102596102543660046139e3565b61069b565b60405190151581526020015b60405180910390f35b61028161027c366004613a25565b6106f7565b005b6102bf6040518060400160405280601a81526020017f4c6f636b52656c65617365546f6b656e506f6f6c20312e352e3100000000000081525081565b6040516102659190613aac565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610265565b610259610321366004613ae1565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610265565b6103a461039f366004613afe565b6108a8565b60405190518152602001610265565b600a5473ffffffffffffffffffffffffffffffffffffffff166102ee565b6102596103df366004613b57565b6109f6565b6102816103f2366004613c26565b610a40565b610281610405366004613b57565b610abb565b610281610418366004613c92565b610b53565b61028161042b366004613ae1565b610c2f565b60095473ffffffffffffffffffffffffffffffffffffffff166102ee565b610281610c7e565b610281610464366004613ae1565b610d4c565b610259610477366004613cbe565b610dcd565b60015473ffffffffffffffffffffffffffffffffffffffff166102ee565b6104ad6104a8366004613cd9565b610de4565b6040516102659190613d14565b6104cd6104c8366004613cbe565b610eb0565b6040516102659190613d6b565b6104e261101b565b6040516102659190613ded565b6102816104fd366004613b57565b61102c565b610515610510366004613cbe565b611144565b604051610265919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102ee565b6102bf61059d366004613cbe565b611219565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b6102816105d6366004613ae1565b6112c9565b6105e36113a4565b6040516102659190613e47565b6105156105fe366004613cbe565b61145c565b610281610611366004613fcf565b61152e565b7f00000000000000000000000000000000000000000000000000000000000000006102ee565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b610281610670366004613c26565b6115b2565b610281610683366004613a25565b611ac4565b610281610696366004613ae1565b611be0565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe1d405660000000000000000000000000000000000000000000000000000000014806106f157506106f182611bf4565b92915050565b600a5473ffffffffffffffffffffffffffffffffffffffff16331461074f576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156107db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ff9190614014565b1015610837576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61087873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611cd8565b604051819033907fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf984017171990600090a350565b6040805160208101909152600081526108c082611dac565b600061091960608401356109146108da60c087018761402d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611fd092505050565b612094565b905061096c61092e6060850160408601613ae1565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169083611cd8565b61097c6060840160408501613ae1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52836040516109da91815260200190565b60405180910390a3604080516020810190915290815292915050565b6000610a388383604051610a0b929190614092565b604080519182900390912067ffffffffffffffff87166000908152600760205291909120600501906122a8565b949350505050565b610a486122c3565b610ab58484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061231692505050565b50505050565b610ac36122c3565b610acc83610dcd565b610b0e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610746565b610b4e8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124cc92505050565b505050565b610b5b6122c3565b6040517f0a861f2a0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff831690630a861f2a90602401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db6282604051610c2391815260200190565b60405180910390a25050565b610c376122c3565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ccf576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610d546122c3565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006106f1600567ffffffffffffffff84166122a8565b6040805180820190915260608082526020820152610e01826125c6565b6040516060830135815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a26040518060400160405280610e5b84602001602081019061059d9190613cbe565b8152602001610ea86040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610ed990600501612752565b90506000815167ffffffffffffffff811115610ef757610ef7613e89565b604051908082528060200260200182016040528015610f2a57816020015b6060815260200190600190039081610f155790505b50905060005b82518110156110135760086000848381518110610f4f57610f4f6140a2565b602002602001015181526020019081526020016000208054610f70906140d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610f9c906140d1565b8015610fe95780601f10610fbe57610100808354040283529160200191610fe9565b820191906000526020600020905b815481529060010190602001808311610fcc57829003601f168201915b5050505050828281518110611000576110006140a2565b6020908102919091010152600101610f30565b509392505050565b60606110276002612752565b905090565b6110346122c3565b61103d83610dcd565b61107f576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610746565b6110bf8282604051611092929190614092565b604080519182900390912067ffffffffffffffff861660009081526007602052919091206005019061275f565b6110fb578282826040517f74f23c7c0000000000000000000000000000000000000000000000000000000081526004016107469392919061416d565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051611137929190614191565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526106f19061276b565b67ffffffffffffffff81166000908152600760205260409020600401805460609190611244906140d1565b80601f0160208091040260200160405190810160405280929190818152602001828054611270906140d1565b80156112bd5780601f10611292576101008083540402835291602001916112bd565b820191906000526020600020905b8154815290600101906020018083116112a057829003601f168201915b50505050509050919050565b6112d16122c3565b73ffffffffffffffffffffffffffffffffffffffff811661131e576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006113b26005612752565b90506000815167ffffffffffffffff8111156113d0576113d0613e89565b6040519080825280602002602001820160405280156113f9578160200160208202803683370190505b50905060005b82518110156114555782818151811061141a5761141a6140a2565b6020026020010151828281518110611434576114346140a2565b67ffffffffffffffff909216602092830291909101909101526001016113ff565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526106f19061276b565b60095473ffffffffffffffffffffffffffffffffffffffff16331480159061156e575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156115a7576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b610b4e83838361281d565b6115ba6122c3565b60005b838110156117a75760008585838181106115d9576115d96140a2565b90506020020160208101906115ee9190613cbe565b9050611605600567ffffffffffffffff831661275f565b611647576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610746565b67ffffffffffffffff8116600090815260076020526040812061166c90600501612752565b905060005b81518110156116d8576116cf82828151811061168f5761168f6140a2565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161275f90919063ffffffff16565b50600101611671565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906117416004830182613976565b600582016000818161175382826139b0565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991694506020019250611795915050565b60405180910390a150506001016115bd565b5060005b81811015611abd5760008383838181106117c7576117c76140a2565b90506020028101906117d991906141a5565b6117e290614271565b90506117f381606001516000612907565b61180281608001516000612907565b806040015151600003611841576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516118599060059067ffffffffffffffff16612a44565b61189e5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610746565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a909102999093161717909416959095179092559092029091176003820155908201516004820190611a2190826143e8565b5060005b826020015151811015611a6557611a5d836000015184602001518381518110611a5057611a506140a2565b60200260200101516124cc565b600101611a25565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c28260000151836040015184606001518560800151604051611aab9493929190614502565b60405180910390a150506001016117ab565b5050505050565b7f0000000000000000000000000000000000000000000000000000000000000000611b1b576040517fe93f8fa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a5473ffffffffffffffffffffffffffffffffffffffff163314611b6e576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b611bb073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612a50565b604051819033907fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb31208890600090a350565b611be86122c3565b611bf181612aae565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf000000000000000000000000000000000000000000000000000000001480611c8757507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806106f157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610b4e9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612b72565b611dbf61032160a0830160808401613ae1565b611e1e57611dd360a0820160808301613ae1565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610746565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611e6a6040840160208501613cbe565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff919061459b565b15611f36576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611f4e611f496040830160208401613cbe565b612c7e565b611f6e611f616040830160208401613cbe565b6103df60a084018461402d565b611fb357611f7f60a082018261402d565b6040517f24eb47e5000000000000000000000000000000000000000000000000000000008152600401610746929190614191565b611bf1611fc66040830160208401613cbe565b8260600135612da4565b6000815160000361200257507f0000000000000000000000000000000000000000000000000000000000000000919050565b815160201461203f57816040517f953576f70000000000000000000000000000000000000000000000000000000081526004016107469190613aac565b6000828060200190518101906120559190614014565b905060ff8111156106f157826040517f953576f70000000000000000000000000000000000000000000000000000000081526004016107469190613aac565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff16036120ca5750816106f1565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1611156121b55760006121247f0000000000000000000000000000000000000000000000000000000000000000846145e7565b9050604d8160ff161115612198576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610746565b6121a381600a614720565b6121ad908561472f565b9150506106f1565b60006121e1837f00000000000000000000000000000000000000000000000000000000000000006145e7565b9050604d8160ff16118061222857506121fb81600a614720565b612225907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61472f565b84115b15612293576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610746565b61229e81600a614720565b610a38908561476a565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314612314576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f000000000000000000000000000000000000000000000000000000000000000061236d576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561240357600083828151811061238d5761238d6140a2565b602002602001015190506123ab816002612deb90919063ffffffff16565b156123fa5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101612370565b5060005b8151811015610b4e576000828281518110612424576124246140a2565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361246857506124c4565b612473600282612e0d565b156124c25760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101612407565b8051600003612507576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff84166000908152600790925260409091206125399060050182612a44565b6125735782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610746929190614781565b600081815260086020526040902061258b83826143e8565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea836040516111379190613aac565b6125d961032160a0830160808401613ae1565b6125ed57611dd360a0820160808301613ae1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6126396040840160208501613cbe565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa1580156126aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ce919061459b565b15612705576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61271d6127186060830160408401613ae1565b612e2f565b6127356127306040830160208401613cbe565b612eae565b611bf16127486040830160208401613cbe565b8260600135612ffc565b606060006122bc83613040565b60006122bc838361309b565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526127f982606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426127dd91906147a4565b85608001516fffffffffffffffffffffffffffffffff1661318e565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61282683610dcd565b612868576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610746565b612873826000612907565b67ffffffffffffffff8316600090815260076020526040902061289690836131b6565b6128a1816000612907565b67ffffffffffffffff831660009081526007602052604090206128c790600201826131b6565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516128fa939291906147b7565b60405180910390a1505050565b8151156129d25781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff1610158061295d575060408201516fffffffffffffffffffffffffffffffff16155b1561299657816040517f8020d124000000000000000000000000000000000000000000000000000000008152600401610746919061483a565b80156129ce576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612a0b575060208201516fffffffffffffffffffffffffffffffff1615155b156129ce57816040517fd68af9cc000000000000000000000000000000000000000000000000000000008152600401610746919061483a565b60006122bc8383613358565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610ab59085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611d2a565b3373ffffffffffffffffffffffffffffffffffffffff821603612afd576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000612bd4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166133a79092919063ffffffff16565b805190915015610b4e5780806020019051810190612bf2919061459b565b610b4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610746565b612c8781610dcd565b612cc9576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610746565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d6c919061459b565b611bf1576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b67ffffffffffffffff821660009081526007602052604090206129ce90600201827f00000000000000000000000000000000000000000000000000000000000000006133b6565b60006122bc8373ffffffffffffffffffffffffffffffffffffffff841661309b565b60006122bc8373ffffffffffffffffffffffffffffffffffffffff8416613358565b7f000000000000000000000000000000000000000000000000000000000000000015611bf157612e60600282613739565b611bf1576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610746565b612eb781610dcd565b612ef9576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610746565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612f72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f969190614876565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611bf1576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b67ffffffffffffffff821660009081526007602052604090206129ce90827f00000000000000000000000000000000000000000000000000000000000000006133b6565b6060816000018054806020026020016040519081016040528092919081815260200182805480156112bd57602002820191906000526020600020905b81548152602001906001019080831161307c5750505050509050919050565b600081815260018301602052604081205480156131845760006130bf6001836147a4565b85549091506000906130d3906001906147a4565b90508082146131385760008660000182815481106130f3576130f36140a2565b9060005260206000200154905080876000018481548110613116576131166140a2565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061314957613149614893565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106f1565b60009150506106f1565b60006131ad8561319e848661476a565b6131a890876148c2565b613768565b95945050505050565b81546000906131df90700100000000000000000000000000000000900463ffffffff16426147a4565b905080156132815760018301548354613227916fffffffffffffffffffffffffffffffff8082169281169185917001000000000000000000000000000000009091041661318e565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546132a7916fffffffffffffffffffffffffffffffff9081169116613768565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906128fa90849061483a565b600081815260018301602052604081205461339f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106f1565b5060006106f1565b6060610a38848460008561377e565b825474010000000000000000000000000000000000000000900460ff1615806133dd575081155b156133e757505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061342d90700100000000000000000000000000000000900463ffffffff16426147a4565b905080156134ed578183111561346f576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546134a99083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661318e565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156135a45773ffffffffffffffffffffffffffffffffffffffff841661354c576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610746565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610746565b848310156136b75760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906135e890826147a4565b6135f2878a6147a4565b6135fc91906148c2565b613606919061472f565b905073ffffffffffffffffffffffffffffffffffffffff861661365f576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610746565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610746565b6136c185846147a4565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415156122bc565b600081831061377757816122bc565b5090919050565b606082471015613810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610746565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161383991906148d5565b60006040518083038185875af1925050503d8060008114613876576040519150601f19603f3d011682016040523d82523d6000602084013e61387b565b606091505b509150915061388c87838387613897565b979650505050505050565b6060831561392d5782516000036139265773ffffffffffffffffffffffffffffffffffffffff85163b613926576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610746565b5081610a38565b610a3883838151156139425781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107469190613aac565b508054613982906140d1565b6000825580601f10613992575050565b601f016020900490600052602060002090810190611bf191906139ca565b5080546000825590600052602060002090810190611bf191905b5b808211156139df57600081556001016139cb565b5090565b6000602082840312156139f557600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146122bc57600080fd5b600060208284031215613a3757600080fd5b5035919050565b60005b83811015613a59578181015183820152602001613a41565b50506000910152565b60008151808452613a7a816020860160208601613a3e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122bc6020830184613a62565b73ffffffffffffffffffffffffffffffffffffffff81168114611bf157600080fd5b600060208284031215613af357600080fd5b81356122bc81613abf565b600060208284031215613b1057600080fd5b813567ffffffffffffffff811115613b2757600080fd5b820161010081850312156122bc57600080fd5b803567ffffffffffffffff81168114613b5257600080fd5b919050565b600080600060408486031215613b6c57600080fd5b613b7584613b3a565b9250602084013567ffffffffffffffff80821115613b9257600080fd5b818601915086601f830112613ba657600080fd5b813581811115613bb557600080fd5b876020828501011115613bc757600080fd5b6020830194508093505050509250925092565b60008083601f840112613bec57600080fd5b50813567ffffffffffffffff811115613c0457600080fd5b6020830191508360208260051b8501011115613c1f57600080fd5b9250929050565b60008060008060408587031215613c3c57600080fd5b843567ffffffffffffffff80821115613c5457600080fd5b613c6088838901613bda565b90965094506020870135915080821115613c7957600080fd5b50613c8687828801613bda565b95989497509550505050565b60008060408385031215613ca557600080fd5b8235613cb081613abf565b946020939093013593505050565b600060208284031215613cd057600080fd5b6122bc82613b3a565b600060208284031215613ceb57600080fd5b813567ffffffffffffffff811115613d0257600080fd5b820160a081850312156122bc57600080fd5b602081526000825160406020840152613d306060840182613a62565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526131ad8282613a62565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613de0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613dce858351613a62565b94509285019290850190600101613d94565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613e3b57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613e09565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613e3b57835167ffffffffffffffff1683529284019291840191600101613e63565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613edb57613edb613e89565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613f2857613f28613e89565b604052919050565b8015158114611bf157600080fd5b80356fffffffffffffffffffffffffffffffff81168114613b5257600080fd5b600060608284031215613f7057600080fd5b6040516060810181811067ffffffffffffffff82111715613f9357613f93613e89565b6040529050808235613fa481613f30565b8152613fb260208401613f3e565b6020820152613fc360408401613f3e565b60408201525092915050565b600080600060e08486031215613fe457600080fd5b613fed84613b3a565b9250613ffc8560208601613f5e565b915061400b8560808601613f5e565b90509250925092565b60006020828403121561402657600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261406257600080fd5b83018035915067ffffffffffffffff82111561407d57600080fd5b602001915036819003821315613c1f57600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c908216806140e557607f821691505b60208210810361411e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff841681526040602082015260006131ad604083018486614124565b602081526000610a38602083018486614124565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181126141d957600080fd5b9190910192915050565b600082601f8301126141f457600080fd5b813567ffffffffffffffff81111561420e5761420e613e89565b61423f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613ee1565b81815284602083860101111561425457600080fd5b816020850160208301376000918101602001919091529392505050565b6000610120823603121561428457600080fd5b61428c613eb8565b61429583613b3a565b815260208084013567ffffffffffffffff808211156142b357600080fd5b9085019036601f8301126142c657600080fd5b8135818111156142d8576142d8613e89565b8060051b6142e7858201613ee1565b918252838101850191858101903684111561430157600080fd5b86860192505b8383101561433d5782358581111561431f5760008081fd5b61432d3689838a01016141e3565b8352509186019190860190614307565b808789015250505050604086013592508083111561435a57600080fd5b5050614368368286016141e3565b60408301525061437b3660608501613f5e565b606082015261438d3660c08501613f5e565b608082015292915050565b601f821115610b4e576000816000526020600020601f850160051c810160208610156143c15750805b601f850160051c820191505b818110156143e0578281556001016143cd565b505050505050565b815167ffffffffffffffff81111561440257614402613e89565b6144168161441084546140d1565b84614398565b602080601f83116001811461446957600084156144335750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556143e0565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156144b657888601518255948401946001909101908401614497565b50858210156144f257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261452681840187613a62565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506145649050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e08301526131ad565b6000602082840312156145ad57600080fd5b81516122bc81613f30565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff82811682821603908111156106f1576106f16145b8565b600181815b8085111561465957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561463f5761463f6145b8565b8085161561464c57918102915b93841c9390800290614605565b509250929050565b600082614670575060016106f1565b8161467d575060006106f1565b8160018114614693576002811461469d576146b9565b60019150506106f1565b60ff8411156146ae576146ae6145b8565b50506001821b6106f1565b5060208310610133831016604e8410600b84101617156146dc575081810a6106f1565b6146e68383614600565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614718576147186145b8565b029392505050565b60006122bc60ff841683614661565b600082614765577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176106f1576106f16145b8565b67ffffffffffffffff83168152604060208201526000610a386040830184613a62565b818103818111156106f1576106f16145b8565b67ffffffffffffffff8416815260e0810161480360208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610a38565b606081016106f182848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561488857600080fd5b81516122bc81613abf565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b808201808211156106f1576106f16145b8565b600082516141d9818460208701613a3e56fea164736f6c6343000818000a", } var LockReleaseTokenPoolABI = LockReleaseTokenPoolMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go index 0fc23b619f7..3d43d16d520 100644 --- a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go +++ b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go @@ -58,8 +58,8 @@ type MultiOCR3BaseOracle struct { } var MultiOCR3HelperMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"AfterConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"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\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"oracleAddress\",\"type\":\"address\"}],\"name\":\"getOracle\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"enumMultiOCR3Base.Role\",\"name\":\"role\",\"type\":\"uint8\"}],\"internalType\":\"structMultiOCR3Base.Oracle\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"setTransmitOcrPluginType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmitWithSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"transmitWithoutSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60a060405234801561001057600080fd5b503360008161003257604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0384811691909117909155811615610062576100628161006d565b5050466080526100e6565b336001600160a01b0382160361009657604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611d256200010960003960008181610edd0152610f290152611d256000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e1461012057806344e65e551461014057806379ba50971461015357600080fd5b8063181f5a77146100c357806326bf9d261461010b575b600080fd5b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e30000000000000006020820152905161010291906114ca565b60405180910390f35b61011e610119366004611591565b61020b565b005b61013361012e36600461161f565b61023a565b6040516101029190611681565b61011e61014e3660046116f4565b6102ca565b61011e61034d565b61011e6101693660046117a7565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b6101d86101d33660046117a7565b61041b565b604051610102919061181b565b61011e6101f33660046118ae565b610593565b61011e610206366004611a1a565b6105a7565b604080516000808252602082019092526004549091506102349060ff16858585858060006105e9565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad611652565b60028111156102be576102be611652565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a92506105e9915050565b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461039e576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61045e6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561051457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116104e9575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561058357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610558575b5050505050815250509050919050565b61059b610972565b6105a4816109c5565b50565b6105af610972565b60005b81518110156105e5576105dd8282815181106105d0576105d0611b83565b6020026020010151610a89565b6001016105b2565b5050565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906106488760a4611be1565b9050826060015115610690578451610661906020611bf4565b865161066e906020611bf4565b6106799060a0611be1565b6106839190611be1565b61068d9082611be1565b90505b3681146106d7576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044015b60405180910390fd5b508151811461071f5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106ce565b610727610eda565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561077557610775611652565b600281111561078657610786611652565b90525090506002816020015160028111156107a3576107a3611652565b1480156108045750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106107df576107df611b83565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b61083a576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561091c576020820151610855906001611c0b565b60ff16855114610891576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108cc576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600087876040516108de929190611c24565b6040519081900381206108f5918b90602001611c34565b60405160208183030381529060405280519060200120905061091a8a82888888610f5b565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146109c3576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b3373ffffffffffffffffffffffffffffffffffffffff821603610a14576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610acd5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610b3a57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610b8f565b6060840151600182015460ff6201000090910416151590151514610b8f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106ce565b60a084015180516101001015610bd45760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b8051600003610c125760056040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b610c858484600301805480602002602001604051908101604052809291908181526020018280548015610c7b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c50575b505050505061116b565b846060015115610e2a57610d008484600201805480602002602001604051908101604052809291908181526020018280548015610c7b5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c5057505050505061116b565b608085015180516101001015610d455760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b6040860151610d55906003611c62565b60ff16815111610d945760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b815181511015610dd35760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841602179055610e1b906002860190602084019061142b565b50610e2885826001611203565b505b610e3684826002611203565b8051610e4b906003850190602084019061142b565b506040858101516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610ec29389939260028a01929190611c85565b60405180910390a1610ed3846113f2565b5050505050565b467f0000000000000000000000000000000000000000000000000000000000000000146109c3576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106ce565b8251600090815b81811015610343576000600188868460208110610f8157610f81611b83565b610f8e91901a601b611c0b565b898581518110610fa057610fa0611b83565b6020026020010151898681518110610fba57610fba611b83565b602002602001015160405160008152602001604052604051610ff8949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561101a573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156110a6576110a6611652565b60028111156110b7576110b7611652565b90525090506001816020015160028111156110d4576110d4611652565b1461110b576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b85161561114e576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050610f62565b60005b81518110156111fe5760ff8316600090815260036020526040812083519091908490849081106111a0576111a0611b83565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560010161116e565b505050565b60005b825181101561023457600083828151811061122357611223611b83565b602002602001015190506000600281111561124057611240611652565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054610100900416600281111561128c5761128c611652565b146112c65760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b73ffffffffffffffffffffffffffffffffffffffff8116611313576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561133957611339611652565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156113de576113de611652565b021790555090505050806001019050611206565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b8280548282559060005260206000209081019282156114a5579160200282015b828111156114a557825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061144b565b506114b19291506114b5565b5090565b5b808211156114b157600081556001016114b6565b60006020808352835180602085015260005b818110156114f8578581018301518582016040015282016114dc565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b80606081018310156102c457600080fd5b60008083601f84011261155a57600080fd5b50813567ffffffffffffffff81111561157257600080fd5b60208301915083602082850101111561158a57600080fd5b9250929050565b6000806000608084860312156115a657600080fd5b6115b08585611537565b9250606084013567ffffffffffffffff8111156115cc57600080fd5b6115d886828701611548565b9497909650939450505050565b803560ff811681146115f657600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146115f657600080fd5b6000806040838503121561163257600080fd5b61163b836115e5565b9150611649602084016115fb565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff16815260208201516040820190600381106116a2576116a2611652565b8060208401525092915050565b60008083601f8401126116c157600080fd5b50813567ffffffffffffffff8111156116d957600080fd5b6020830191508360208260051b850101111561158a57600080fd5b60008060008060008060008060e0898b03121561171057600080fd5b61171a8a8a611537565b9750606089013567ffffffffffffffff8082111561173757600080fd5b6117438c838d01611548565b909950975060808b013591508082111561175c57600080fd5b6117688c838d016116af565b909750955060a08b013591508082111561178157600080fd5b5061178e8b828c016116af565b999c989b50969995989497949560c00135949350505050565b6000602082840312156117b957600080fd5b6117c2826115e5565b9392505050565b60008151808452602080850194506020840160005b8381101561181057815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016117de565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261186a60e08401826117c9565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c08501526118a582826117c9565b95945050505050565b6000602082840312156118c057600080fd5b6117c2826115fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561191b5761191b6118c9565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611968576119686118c9565b604052919050565b600067ffffffffffffffff82111561198a5761198a6118c9565b5060051b60200190565b803580151581146115f657600080fd5b600082601f8301126119b557600080fd5b813560206119ca6119c583611970565b611921565b8083825260208201915060208460051b8701019350868411156119ec57600080fd5b602086015b84811015611a0f57611a02816115fb565b83529183019183016119f1565b509695505050505050565b60006020808385031215611a2d57600080fd5b823567ffffffffffffffff80821115611a4557600080fd5b818501915085601f830112611a5957600080fd5b8135611a676119c582611970565b81815260059190911b83018401908481019088831115611a8657600080fd5b8585015b83811015611b7657803585811115611aa157600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611ad65760008081fd5b611ade6118f8565b8882013581526040611af18184016115e5565b8a8301526060611b028185016115e5565b8284015260809150611b15828501611994565b9083015260a08381013589811115611b2d5760008081fd5b611b3b8f8d838801016119a4565b838501525060c0840135915088821115611b555760008081fd5b611b638e8c848701016119a4565b9083015250845250918601918601611a8a565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611bb2565b80820281158282048414176102c4576102c4611bb2565b60ff81811683821601908111156102c4576102c4611bb2565b8183823760009101908152919050565b828152606082602083013760800192915050565b6020810160068310611c5c57611c5c611652565b91905290565b60ff8181168382160290811690818114611c7e57611c7e611bb2565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611cec57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611cba565b50508481036060860152611d0081886117c9565b935050505060ff83166080830152969550505050505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"AfterConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"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\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"oracleAddress\",\"type\":\"address\"}],\"name\":\"getOracle\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"enumMultiOCR3Base.Role\",\"name\":\"role\",\"type\":\"uint8\"}],\"internalType\":\"structMultiOCR3Base.Oracle\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"setTransmitOcrPluginType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmitWithSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"transmitWithoutSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x60a060405234801561001057600080fd5b503360008161003257604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0384811691909117909155811615610062576100628161006d565b5050466080526100e6565b336001600160a01b0382160361009657604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611d256200010960003960008181610edd0152610f290152611d256000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e146101205780633ecdb95b1461014057806379ba50971461015357600080fd5b806310061068146100c3578063181f5a77146100d8575b600080fd5b6100d66100d1366004611524565b61020b565b005b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e3000000000000000602082015290516101179190611578565b60405180910390f35b61013361012e36600461161f565b61023a565b6040516101179190611681565b6100d661014e3660046116f4565b6102ca565b6100d661034d565b6100d66101693660046117a7565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610117565b6101d86101d33660046117a7565b61041b565b604051610117919061181b565b6100d66101f33660046118ae565b610593565b6100d6610206366004611a1a565b6105a7565b604080516000808252602082019092526004549091506102349060ff16858585858060006105e9565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad611652565b60028111156102be576102be611652565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a92506105e9915050565b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461039e576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61045e6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561051457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116104e9575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561058357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610558575b5050505050815250509050919050565b61059b610972565b6105a4816109c5565b50565b6105af610972565b60005b81518110156105e5576105dd8282815181106105d0576105d0611b83565b6020026020010151610a89565b6001016105b2565b5050565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590610648876084611be1565b9050826060015115610690578451610661906020611bf4565b865161066e906020611bf4565b6106799060a0611be1565b6106839190611be1565b61068d9082611be1565b90505b3681146106d7576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044015b60405180910390fd5b508151811461071f5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106ce565b610727610eda565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561077557610775611652565b600281111561078657610786611652565b90525090506002816020015160028111156107a3576107a3611652565b1480156108045750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106107df576107df611b83565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b61083a576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561091c576020820151610855906001611c0b565b60ff16855114610891576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108cc576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600087876040516108de929190611c24565b6040519081900381206108f5918b90602001611c34565b60405160208183030381529060405280519060200120905061091a8a82888888610f5b565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146109c3576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b3373ffffffffffffffffffffffffffffffffffffffff821603610a14576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610acd5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610b3a57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610b8f565b6060840151600182015460ff6201000090910416151590151514610b8f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106ce565b60a084015180516101001015610bd45760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b8051600003610c125760056040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b610c858484600301805480602002602001604051908101604052809291908181526020018280548015610c7b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c50575b505050505061116b565b846060015115610e2a57610d008484600201805480602002602001604051908101604052809291908181526020018280548015610c7b5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c5057505050505061116b565b608085015180516101001015610d455760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b6040860151610d55906003611c62565b60ff16815111610d945760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b815181511015610dd35760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841602179055610e1b906002860190602084019061142b565b50610e2885826001611203565b505b610e3684826002611203565b8051610e4b906003850190602084019061142b565b506040858101516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610ec29389939260028a01929190611c85565b60405180910390a1610ed3846113f2565b5050505050565b467f0000000000000000000000000000000000000000000000000000000000000000146109c3576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106ce565b8251600090815b81811015610343576000600188868460208110610f8157610f81611b83565b610f8e91901a601b611c0b565b898581518110610fa057610fa0611b83565b6020026020010151898681518110610fba57610fba611b83565b602002602001015160405160008152602001604052604051610ff8949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561101a573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156110a6576110a6611652565b60028111156110b7576110b7611652565b90525090506001816020015160028111156110d4576110d4611652565b1461110b576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b85161561114e576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050610f62565b60005b81518110156111fe5760ff8316600090815260036020526040812083519091908490849081106111a0576111a0611b83565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560010161116e565b505050565b60005b825181101561023457600083828151811061122357611223611b83565b602002602001015190506000600281111561124057611240611652565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054610100900416600281111561128c5761128c611652565b146112c65760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b73ffffffffffffffffffffffffffffffffffffffff8116611313576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561133957611339611652565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156113de576113de611652565b021790555090505050806001019050611206565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b8280548282559060005260206000209081019282156114a5579160200282015b828111156114a557825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061144b565b506114b19291506114b5565b5090565b5b808211156114b157600081556001016114b6565b80604081018310156102c457600080fd5b60008083601f8401126114ed57600080fd5b50813567ffffffffffffffff81111561150557600080fd5b60208301915083602082850101111561151d57600080fd5b9250929050565b60008060006060848603121561153957600080fd5b61154385856114ca565b9250604084013567ffffffffffffffff81111561155f57600080fd5b61156b868287016114db565b9497909650939450505050565b60006020808352835180602085015260005b818110156115a65785810183015185820160400152820161158a565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803560ff811681146115f657600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146115f657600080fd5b6000806040838503121561163257600080fd5b61163b836115e5565b9150611649602084016115fb565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff16815260208201516040820190600381106116a2576116a2611652565b8060208401525092915050565b60008083601f8401126116c157600080fd5b50813567ffffffffffffffff8111156116d957600080fd5b6020830191508360208260051b850101111561151d57600080fd5b60008060008060008060008060c0898b03121561171057600080fd5b61171a8a8a6114ca565b9750604089013567ffffffffffffffff8082111561173757600080fd5b6117438c838d016114db565b909950975060608b013591508082111561175c57600080fd5b6117688c838d016116af565b909750955060808b013591508082111561178157600080fd5b5061178e8b828c016116af565b999c989b50969995989497949560a00135949350505050565b6000602082840312156117b957600080fd5b6117c2826115e5565b9392505050565b60008151808452602080850194506020840160005b8381101561181057815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016117de565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261186a60e08401826117c9565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c08501526118a582826117c9565b95945050505050565b6000602082840312156118c057600080fd5b6117c2826115fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561191b5761191b6118c9565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611968576119686118c9565b604052919050565b600067ffffffffffffffff82111561198a5761198a6118c9565b5060051b60200190565b803580151581146115f657600080fd5b600082601f8301126119b557600080fd5b813560206119ca6119c583611970565b611921565b8083825260208201915060208460051b8701019350868411156119ec57600080fd5b602086015b84811015611a0f57611a02816115fb565b83529183019183016119f1565b509695505050505050565b60006020808385031215611a2d57600080fd5b823567ffffffffffffffff80821115611a4557600080fd5b818501915085601f830112611a5957600080fd5b8135611a676119c582611970565b81815260059190911b83018401908481019088831115611a8657600080fd5b8585015b83811015611b7657803585811115611aa157600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611ad65760008081fd5b611ade6118f8565b8882013581526040611af18184016115e5565b8a8301526060611b028185016115e5565b8284015260809150611b15828501611994565b9083015260a08381013589811115611b2d5760008081fd5b611b3b8f8d838801016119a4565b838501525060c0840135915088821115611b555760008081fd5b611b638e8c848701016119a4565b9083015250845250918601918601611a8a565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611bb2565b80820281158282048414176102c4576102c4611bb2565b60ff81811683821601908111156102c4576102c4611bb2565b8183823760009101908152919050565b828152604082602083013760600192915050565b6020810160068310611c5c57611c5c611652565b91905290565b60ff8181168382160290811690818114611c7e57611c7e611bb2565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611cec57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611cba565b50508481036060860152611d0081886117c9565b935050505060ff83166080830152969550505050505056fea164736f6c6343000818000a", } var MultiOCR3HelperABI = MultiOCR3HelperMetaData.ABI @@ -334,27 +334,27 @@ func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransferOwnership(to c return _MultiOCR3Helper.Contract.TransferOwnership(&_MultiOCR3Helper.TransactOpts, to) } -func (_MultiOCR3Helper *MultiOCR3HelperTransactor) TransmitWithSignatures(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperTransactor) TransmitWithSignatures(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _MultiOCR3Helper.contract.Transact(opts, "transmitWithSignatures", reportContext, report, rs, ss, rawVs) } -func (_MultiOCR3Helper *MultiOCR3HelperSession) TransmitWithSignatures(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperSession) TransmitWithSignatures(reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _MultiOCR3Helper.Contract.TransmitWithSignatures(&_MultiOCR3Helper.TransactOpts, reportContext, report, rs, ss, rawVs) } -func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransmitWithSignatures(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransmitWithSignatures(reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _MultiOCR3Helper.Contract.TransmitWithSignatures(&_MultiOCR3Helper.TransactOpts, reportContext, report, rs, ss, rawVs) } -func (_MultiOCR3Helper *MultiOCR3HelperTransactor) TransmitWithoutSignatures(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperTransactor) TransmitWithoutSignatures(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte) (*types.Transaction, error) { return _MultiOCR3Helper.contract.Transact(opts, "transmitWithoutSignatures", reportContext, report) } -func (_MultiOCR3Helper *MultiOCR3HelperSession) TransmitWithoutSignatures(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperSession) TransmitWithoutSignatures(reportContext [2][32]byte, report []byte) (*types.Transaction, error) { return _MultiOCR3Helper.Contract.TransmitWithoutSignatures(&_MultiOCR3Helper.TransactOpts, reportContext, report) } -func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransmitWithoutSignatures(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransmitWithoutSignatures(reportContext [2][32]byte, report []byte) (*types.Transaction, error) { return _MultiOCR3Helper.Contract.TransmitWithoutSignatures(&_MultiOCR3Helper.TransactOpts, reportContext, report) } @@ -1056,9 +1056,9 @@ type MultiOCR3HelperInterface interface { TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - TransmitWithSignatures(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) + TransmitWithSignatures(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) - TransmitWithoutSignatures(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) + TransmitWithoutSignatures(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte) (*types.Transaction, error) FilterAfterConfigSet(opts *bind.FilterOpts) (*MultiOCR3HelperAfterConfigSetIterator, error) diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 6bc1b8d2d4f..b582b60cff6 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -155,8 +155,8 @@ type OffRampStaticConfig struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyBatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationNotAllowedInExecutionPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationRequiredInCommitPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllSourceChainConfigs\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReport[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006bc738038062006bc7833981016040819052620000359162000880565b336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620001c4565b50504660805260208301516001600160a01b03161580620000b6575060408301516001600160a01b0316155b80620000cd575060608301516001600160a01b0316155b15620000ec576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b0316600003620001185760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001b0826200023e565b620001bb816200032c565b50505062000c72565b336001600160a01b03821603620001ee57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b031662000267576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516001600160a01b039889166001600160c01b03199097168717600160a01b63ffffffff958616021760ff60c01b1916600160c01b911515919091021790965560608089018051600580546001600160a01b031916918b169190911790558251968752935190921693850193909352935115159183019190915251909216908201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9060800160405180910390a150565b60005b8151811015620005c1576000828281518110620003505762000350620009aa565b60200260200101519050600081602001519050806001600160401b03166000036200038e5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003b7576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526008602052604090206060830151600182018054620003e590620009c0565b905060000362000448578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004b9565b8154600160a81b90046001600160401b03166001148015906200048b57508051602082012060405162000480906001850190620009fc565b604051809103902014155b15620004b957604051632105803760e11b81526001600160401b038416600482015260240160405180910390fd5b80511580620004ef5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200050e576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200051e828262000acf565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b0319909116171782556200056d60066001600160401b038516620005c5565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b83604051620005a9919062000b9b565b60405180910390a2505050508060010190506200032f565b5050565b6000620005d38383620005dc565b90505b92915050565b60008181526001830160205260408120546200062557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620005d6565b506000620005d6565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200066957620006696200062e565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200069a576200069a6200062e565b604052919050565b80516001600160401b0381168114620006ba57600080fd5b919050565b6001600160a01b0381168114620006d557600080fd5b50565b80518015158114620006ba57600080fd5b6000601f83601f840112620006fd57600080fd5b825160206001600160401b03808311156200071c576200071c6200062e565b8260051b6200072d8382016200066f565b93845286810183019383810190898611156200074857600080fd5b84890192505b858310156200087357825184811115620007685760008081fd5b89016080601f19828d038101821315620007825760008081fd5b6200078c62000644565b888401516200079b81620006bf565b81526040620007ac858201620006a2565b8a8301526060620007bf818701620006d8565b83830152938501519389851115620007d75760008081fd5b84860195508f603f870112620007ef57600094508485fd5b8a8601519450898511156200080857620008086200062e565b620008198b858f880116016200066f565b93508484528f82868801011115620008315760008081fd5b60005b8581101562000851578681018301518582018d01528b0162000834565b5060009484018b0194909452509182015283525091840191908401906200074e565b9998505050505050505050565b60008060008385036101208112156200089857600080fd5b6080811215620008a757600080fd5b620008b162000644565b620008bc86620006a2565b81526020860151620008ce81620006bf565b60208201526040860151620008e381620006bf565b60408201526060860151620008f881620006bf565b606082015293506080607f19820112156200091257600080fd5b506200091d62000644565b60808501516200092d81620006bf565b815260a085015163ffffffff811681146200094757600080fd5b60208201526200095a60c08601620006d8565b604082015260e08501516200096f81620006bf565b60608201526101008501519092506001600160401b038111156200099257600080fd5b620009a086828701620006e9565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680620009d557607f821691505b602082108103620009f657634e487b7160e01b600052602260045260246000fd5b50919050565b600080835462000a0c81620009c0565b6001828116801562000a27576001811462000a3d5762000a6e565b60ff198416875282151583028701945062000a6e565b8760005260208060002060005b8581101562000a655781548a82015290840190820162000a4a565b50505082870194505b50929695505050505050565b601f82111562000aca576000816000526020600020601f850160051c8101602086101562000aa55750805b601f850160051c820191505b8181101562000ac65782815560010162000ab1565b5050505b505050565b81516001600160401b0381111562000aeb5762000aeb6200062e565b62000b038162000afc8454620009c0565b8462000a7a565b602080601f83116001811462000b3b576000841562000b225750858301515b600019600386901b1c1916600185901b17855562000ac6565b600085815260208120601f198616915b8281101562000b6c5788860151825594840194600190910190840162000b4b565b508582101562000b8b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000bf081620009c0565b8060a089015260c0600183166000811462000c14576001811462000c315762000c63565b60ff19841660c08b015260c083151560051b8b0101945062000c63565b85600052602060002060005b8481101562000c5a5781548c820185015290880190890162000c3d565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615ed862000cef600039600081816102070152612be30152600081816101d80152612eab0152600081816101a9015281816105820152818161073201526125e301526000818161017a0152818161278e0152612845015260008181611d120152611d450152615ed86000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80637437ff9f116100ad578063c673e58411610071578063c673e58414610474578063ccd37ba314610494578063e9d68a8e146104d8578063f2fde38b146104f8578063f716f99f1461050b57600080fd5b80637437ff9f1461037357806379ba5097146104305780637edf52f41461043857806385572ffb1461044b5780638da5cb5b1461045957600080fd5b80633f4b04aa116100f45780633f4b04aa146102fc5780635215505b146103175780635e36480c1461032d5780635e7bb0081461034d57806360987c201461036057600080fd5b806304666f9c1461013157806306285c6914610146578063181f5a771461028d5780632d04ab76146102d6578063311cd513146102e9575b600080fd5b61014461013f366004613e1e565b61051e565b005b61023760408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b604051610284919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102c96040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102849190613f8c565b6101446102e436600461403c565b610532565b6101446102f73660046140ee565b610a46565b600b546040516001600160401b039091168152602001610284565b61031f610aaf565b604051610284929190614188565b61034061033b366004614229565b610d0a565b6040516102849190614286565b61014461035b3660046147ef565b610d5f565b61014461036e366004614a33565b610fee565b6103e960408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526004546001600160a01b038082168352600160a01b820463ffffffff166020840152600160c01b90910460ff16151592820192909252600554909116606082015290565b604051610284919081516001600160a01b03908116825260208084015163ffffffff1690830152604080840151151590830152606092830151169181019190915260800190565b6101446112a5565b610144610446366004614ac7565b611328565b61014461012c366004614b2c565b6001546040516001600160a01b039091168152602001610284565b610487610482366004614b77565b611339565b6040516102849190614bd7565b6104ca6104a2366004614c4c565b6001600160401b03919091166000908152600a60209081526040808320938352929052205490565b604051908152602001610284565b6104eb6104e6366004614c76565b611497565b6040516102849190614c91565b610144610506366004614ca4565b6115a3565b610144610519366004614d29565b6115b4565b6105266115f6565b61052f81611623565b50565b60006105408789018961507e565b6004805491925090600160c01b900460ff166105ea57602082015151156105ea5760208201516040808401519051633854844f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926370a9089e926105b992309291906004016152a6565b60006040518083038186803b1580156105d157600080fd5b505afa1580156105e5573d6000803e3d6000fd5b505050505b8151515115158061060057508151602001515115155b156106cb57600b5460208b0135906001600160401b03808316911610156106a357600b805467ffffffffffffffff19166001600160401b03831617905581548351604051633937306f60e01b81526001600160a01b0390921691633937306f9161066c916004016153db565b600060405180830381600087803b15801561068657600080fd5b505af115801561069a573d6000803e3d6000fd5b505050506106c9565b8260200151516000036106c957604051632261116760e01b815260040160405180910390fd5b505b60005b826020015151811015610986576000836020015182815181106106f3576106f3615309565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079d91906153ee565b156107cb57604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107d6826118ac565b9050806001016040516107e99190615445565b6040518091039020836020015180519060200120146108265782602001518160010160405163b80d8fa960e01b81526004016107c2929190615538565b60408301518154600160a81b90046001600160401b039081169116141580610867575082606001516001600160401b031683604001516001600160401b0316115b156108ac57825160408085015160608601519151636af0786b60e11b81526001600160401b0393841660048201529083166024820152911660448201526064016107c2565b6080830151806108cf5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600a60209081526040808320848452909152902054156109275783516040516332cf0cbf60e01b81526001600160401b039091166004820152602481018290526044016107c2565b6060840151610937906001615573565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600a6020908152604080832094835293905291909120429055506001016106ce565b50602082015182516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e4926109be92909161559a565b60405180910390a1610a3a60008b8b8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d9182918501908490808284376000920191909152508c92506118f8915050565b50505050505050505050565b610a86610a55828401846155bf565b6040805160008082526020820190925290610a80565b6060815260200190600190039081610a6b5790505b50611bf1565b604080516000808252602082019092529050610aa96001858585858660006118f8565b50505050565b6060806000610abe6006611cb4565b6001600160401b03811115610ad557610ad5613c3e565b604051908082528060200260200182016040528015610b2657816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610af35790505b5090506000610b356006611cb4565b6001600160401b03811115610b4c57610b4c613c3e565b604051908082528060200260200182016040528015610b75578160200160208202803683370190505b50905060005b610b856006611cb4565b811015610d0157610b97600682611cbe565b828281518110610ba957610ba9615309565b60200260200101906001600160401b031690816001600160401b03168152505060086000838381518110610bdf57610bdf615309565b6020908102919091018101516001600160401b039081168352828201939093526040918201600020825160808101845281546001600160a01b038116825260ff600160a01b820416151593820193909352600160a81b90920490931691810191909152600182018054919291606084019190610c5a9061540b565b80601f0160208091040260200160405190810160405280929190818152602001828054610c869061540b565b8015610cd35780601f10610ca857610100808354040283529160200191610cd3565b820191906000526020600020905b815481529060010190602001808311610cb657829003601f168201915b505050505081525050838281518110610cee57610cee615309565b6020908102919091010152600101610b7b565b50939092509050565b6000610d18600160046155f3565b6002610d2560808561561c565b6001600160401b0316610d389190615642565b610d428585611cca565b901c166003811115610d5657610d5661425c565b90505b92915050565b610d67611d0f565b815181518114610d8a576040516320f8fd5960e21b815260040160405180910390fd5b60005b81811015610fde576000848281518110610da957610da9615309565b60200260200101519050600081602001515190506000858481518110610dd157610dd1615309565b6020026020010151905080518214610dfc576040516320f8fd5960e21b815260040160405180910390fd5b60005b82811015610fcf576000828281518110610e1b57610e1b615309565b6020026020010151600001519050600085602001518381518110610e4157610e41615309565b6020026020010151905081600014610e95578060800151821015610e95578551815151604051633a98d46360e11b81526001600160401b0390921660048301526024820152604481018390526064016107c2565b838381518110610ea757610ea7615309565b602002602001015160200151518160a001515114610ef457805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b031660248201526044016107c2565b60005b8160a0015151811015610fc1576000858581518110610f1857610f18615309565b6020026020010151602001518281518110610f3557610f35615309565b602002602001015163ffffffff16905080600014610fb85760008360a001518381518110610f6557610f65615309565b60200260200101516040015163ffffffff16905080821015610fb6578351516040516348e617b360e01b815260048101919091526024810184905260448101829052606481018390526084016107c2565b505b50600101610ef7565b505050806001019050610dff565b50505050806001019050610d8d565b50610fe98383611bf1565b505050565b33301461100e576040516306e34e6560e31b815260040160405180910390fd5b604080516000808252602082019092528161104b565b60408051808201909152600080825260208201528152602001906001900390816110245790505b5060a087015151909150156110815761107e8660a001518760200151886060015189600001516020015189898989611d77565b90505b6040805160a081018252875151815287516020908101516001600160401b03168183015288015181830152908701516060820152608081018290526005546001600160a01b03168015611174576040516308d450a160e01b81526001600160a01b038216906308d450a1906110fa9085906004016156fa565b600060405180830381600087803b15801561111457600080fd5b505af1925050508015611125575060015b611174573d808015611153576040519150601f19603f3d011682016040523d82523d6000602084013e611158565b606091505b50806040516309c2532560e01b81526004016107c29190613f8c565b60408801515115801561118957506080880151155b806111a0575060608801516001600160a01b03163b155b806111c7575060608801516111c5906001600160a01b03166385572ffb60e01b611f28565b155b156111d45750505061129e565b87516020908101516001600160401b03166000908152600890915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392611232928992611388929160040161570d565b6000604051808303816000875af1158015611251573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112799190810190615749565b509150915081610a3a57806040516302a35ba360e21b81526004016107c29190613f8c565b5050505050565b6000546001600160a01b031633146112d05760405163015aa1e360e11b815260040160405180910390fd5b600180546001600160a01b0319808216339081179093556000805490911681556040516001600160a01b03909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6113306115f6565b61052f81611f44565b61137c6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561142557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611407575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561148757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611469575b5050505050815250509050919050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260088352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916115239061540b565b80601f016020809104026020016040519081016040528092919081815260200182805461154f9061540b565b80156114875780601f1061157157610100808354040283529160200191611487565b820191906000526020600020905b81548152906001019060200180831161157f57505050919092525091949350505050565b6115ab6115f6565b61052f81612049565b6115bc6115f6565b60005b81518110156115f2576115ea8282815181106115dd576115dd615309565b60200260200101516120c2565b6001016115bf565b5050565b6001546001600160a01b03163314611621576040516315ae3a6f60e11b815260040160405180910390fd5b565b60005b81518110156115f257600082828151811061164357611643615309565b60200260200101519050600081602001519050806001600160401b03166000036116805760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166116a8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260086020526040902060608301516001820180546116d49061540b565b905060000361173657815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161179f565b8154600160a81b90046001600160401b031660011480159061177657508051602082012060405161176b906001850190615445565b604051809103902014155b1561179f57604051632105803760e11b81526001600160401b03841660048201526024016107c2565b805115806117d45750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156117f2576040516342bcdf7f60e11b815260040160405180910390fd5b60018201611800828261582e565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b029290921674ffffffffffffffffffffffffffffffffffffffffff199091161717825561185b60066001600160401b0385166123ec565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b8360405161189591906158ed565b60405180910390a250505050806001019050611626565b6001600160401b03811660009081526008602052604081208054600160a01b900460ff16610d595760405163ed053c5960e01b81526001600160401b03841660048201526024016107c2565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119578760a461593b565b905082606001511561199f578451611970906020615642565b865161197d906020615642565b6119889060a061593b565b611992919061593b565b61199c908261593b565b90505b3681146119c857604051638e1192e160e01b8152600481018290523660248201526044016107c2565b50815181146119f75781516040516324f7d61360e21b81526004810191909152602481018290526044016107c2565b6119ff611d0f565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611a4d57611a4d61425c565b6002811115611a5e57611a5e61425c565b9052509050600281602001516002811115611a7b57611a7b61425c565b148015611acf5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611ab757611ab7615309565b6000918252602090912001546001600160a01b031633145b611aec57604051631b41e11d60e31b815260040160405180910390fd5b50816060015115611b9c576020820151611b0790600161594e565b60ff16855114611b2a576040516371253a2560e01b815260040160405180910390fd5b8351855114611b4c5760405163a75d88af60e01b815260040160405180910390fd5b60008787604051611b5e929190615967565b604051908190038120611b75918b90602001615977565b604051602081830303815290604052805190602001209050611b9a8a828888886123f8565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b8151600003611c135760405163c2e5347d60e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611c56565b604080518082019091526000815260606020820152815260200190600190039081611c2e5790505b50905060005b845181101561129e57611cac858281518110611c7a57611c7a615309565b602002602001015184611ca657858381518110611c9957611c99615309565b60200260200101516125b5565b836125b5565b600101611c5c565b6000610d59825490565b6000610d568383612e46565b6001600160401b038216600090815260096020526040812081611cee60808561598b565b6001600160401b031681526020810191909152604001600020549392505050565b467f00000000000000000000000000000000000000000000000000000000000000001461162157604051630f01ce8560e01b81527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016107c2565b606088516001600160401b03811115611d9257611d92613c3e565b604051908082528060200260200182016040528015611dd757816020015b6040805180820190915260008082526020820152815260200190600190039081611db05790505b509050811560005b8a51811015611f1a5781611e7757848482818110611dff57611dff615309565b9050602002016020810190611e1491906159b1565b63ffffffff1615611e7757848482818110611e3157611e31615309565b9050602002016020810190611e4691906159b1565b8b8281518110611e5857611e58615309565b60200260200101516040019063ffffffff16908163ffffffff16815250505b611ef58b8281518110611e8c57611e8c615309565b60200260200101518b8b8b8b8b87818110611ea957611ea9615309565b9050602002810190611ebb91906159cc565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e7092505050565b838281518110611f0757611f07615309565b6020908102919091010152600101611ddf565b505098975050505050505050565b6000611f3383613150565b8015610d565750610d568383613183565b80516001600160a01b0316611f6c576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516001600160a01b039889167fffffffffffffffff0000000000000000000000000000000000000000000000009097168717600160a01b63ffffffff958616021760ff60c01b1916600160c01b911515919091021790965560608089018051600580546001600160a01b031916918b169190911790558251968752935190921693850193909352935115159183019190915251909216908201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9060800160405180910390a150565b336001600160a01b0382160361207257604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120ed576000604051631b3fab5160e11b81526004016107c29190615a12565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361213e576060840151600182018054911515620100000262ff00001990921691909117905561217a565b6060840151600182015460ff620100009091041615159015151461217a576040516321fd80df60e21b815260ff841660048201526024016107c2565b60a0840151805161010010156121a6576001604051631b3fab5160e11b81526004016107c29190615a12565b80516000036121cb576005604051631b3fab5160e11b81526004016107c29190615a12565b612231848460030180548060200260200160405190810160405280929190818152602001828054801561222757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612209575b505050505061320d565b8460600151156123615761229f8484600201805480602002602001604051908101604052809291908181526020018280548015612227576020028201919060005260206000209081546001600160a01b0316815260019091019060200180831161220957505050505061320d565b6080850151805161010010156122cb576002604051631b3fab5160e11b81526004016107c29190615a12565b60408601516122db906003615a2c565b60ff16815111612301576003604051631b3fab5160e11b81526004016107c29190615a12565b815181511015612327576001604051631b3fab5160e11b81526004016107c29190615a12565b805160018401805461ff00191661010060ff8416021790556123529060028601906020840190613bc4565b5061235f85826001613276565b505b61236d84826002613276565b80516123829060038501906020840190613bc4565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123db9389939260028a01929190615a48565b60405180910390a161129e846133d1565b6000610d568383613454565b8251600090815b818110156125ab57600060018886846020811061241e5761241e615309565b61242b91901a601b61594e565b89858151811061243d5761243d615309565b602002602001015189868151811061245757612457615309565b602002602001015160405160008152602001604052604051612495949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156124b7573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b038516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156125185761251861425c565b60028111156125295761252961425c565b90525090506001816020015160028111156125465761254661425c565b1461256457604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561258e57604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b8517945050508060010190506123ff565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612632573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265691906153ee565b156126c757801561268557604051637edeb53960e11b81526001600160401b03831660048201526024016107c2565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60208401515160008190036126fd57845160405163676cf24b60e11b81526001600160401b0390911660048201526024016107c2565b8460400151518114612722576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561273c5761273c613c3e565b604051908082528060200260200182016040528015612765578160200160208202803683370190505b50905060007f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f857f00000000000000000000000000000000000000000000000000000000000000006127b6886118ac565b6001016040516127c69190615445565b6040519081900381206127fe949392916020019384526001600160401b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120905060005b838110156129345760008860200151828151811061283957612839615309565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146128b05780516040908101519051631c21951160e11b81526001600160401b0390911660048201526024016107c2565b866001600160401b03168160000151602001516001600160401b03161461290457805160200151604051636c95f1eb60e01b81526001600160401b03808a16600483015290911660248201526044016107c2565b61290e81846134a3565b84838151811061292057612920615309565b602090810291909101015250600101612819565b5050600061294c858389606001518a608001516135ab565b90508060000361297a57604051633ee8bd3f60e11b81526001600160401b03861660048201526024016107c2565b60005b838110156125ab5760005a90506000896020015183815181106129a2576129a2615309565b6020026020010151905060006129c089836000015160600151610d0a565b905060008160038111156129d6576129d661425c565b14806129f3575060038160038111156129f1576129f161425c565b145b612a4957815160600151604080516001600160401b03808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612e3e565b60608815612b28578a8581518110612a6357612a63615309565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff16612a9188426155f3565b1190508080612ab157506003836003811115612aaf57612aaf61425c565b145b612ad9576040516354e7e43160e11b81526001600160401b038c1660048201526024016107c2565b8b8681518110612aeb57612aeb615309565b602002602001015160000151600014612b22578b8681518110612b1057612b10615309565b60209081029190910101515160808501525b50612b94565b6000826003811115612b3c57612b3c61425c565b14612b9457825160600151604080516001600160401b03808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612e3e565b8251608001516001600160401b031615612c6a576000826003811115612bbc57612bbc61425c565b03612c6a5782516080015160208401516040516370701e5760e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612c1a928f929190600401615afa565b6020604051808303816000875af1158015612c39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5d91906153ee565b612c6a5750505050612e3e565b60008c604001518681518110612c8257612c82615309565b6020026020010151905080518460a001515114612ccc57835160600151604051631cfe6d8b60e01b81526001600160401b03808e16600483015290911660248201526044016107c2565b612ce08b85600001516060015160016135e8565b600080612cee86848661368d565b91509150612d058d876000015160600151846135e8565b8b15612d5c576003826003811115612d1f57612d1f61425c565b03612d5c576000856003811115612d3857612d3861425c565b14612d5c57855151604051632b11b8d960e01b81526107c291908390600401615b26565b6002826003811115612d7057612d7061425c565b14612db1576003826003811115612d8957612d8961425c565b14612db1578551606001516040516349362d1f60e11b81526107c2918f918590600401615b3f565b8560000151600001518660000151606001516001600160401b03168e6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612e0957612e09615309565b602002602001015186865a612e1e908f6155f3565b604051612e2e9493929190615b64565b60405180910390a4505050505050505b60010161297d565b6000826000018281548110612e5d57612e5d615309565b9060005260206000200154905092915050565b6040805180820190915260008082526020820152602086015160405163bbe4f6db60e01b81526001600160a01b0380831660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015612ef4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f189190615b9b565b90506001600160a01b0381161580612f475750612f456001600160a01b03821663aff2afbf60e01b611f28565b155b15612f705760405163ae9b4ce960e01b81526001600160a01b03821660048201526024016107c2565b600080612f8888858c6040015163ffffffff16613741565b91509150600080600061303b6040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f608001518152602001896001600160a01b031681526020018f6000015181526020018f6060015181526020018b8152506040516024016130059190615bb8565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b17905287866113886084613824565b92509250925082613061578160405163e1cd550960e01b81526004016107c29190613f8c565b8151602014613090578151604051631e3be00960e21b81526020600482015260248101919091526044016107c2565b6000828060200190518101906130a69190615c84565b9050866001600160a01b03168c6001600160a01b0316146131225760006130d78d8a6130d2868a6155f3565b613741565b509050868110806130f15750816130ee88836155f3565b14155b156131205760405163a966e21f60e01b81526004810183905260248101889052604481018290526064016107c2565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000613163826301ffc9a760e01b613183565b8015610d59575061317c826001600160e01b0319613183565b1592915050565b6040516001600160e01b031982166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d915060005190508280156131f6575060208210155b80156132025750600081115b979650505050505050565b60005b8151811015610fe95760ff83166000908152600360205260408120835190919084908490811061324257613242615309565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613210565b60005b8251811015610aa957600083828151811061329657613296615309565b60200260200101519050600060028111156132b3576132b361425c565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156132f2576132f261425c565b14613313576004604051631b3fab5160e11b81526004016107c29190615a12565b6001600160a01b03811661333a5760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156133605761336061425c565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156133bd576133bd61425c565b021790555090505050806001019050613279565b60ff818116600081815260026020526040902060010154620100009004909116906134295780613414576040516317bd8dd160e11b815260040160405180910390fd5b600b805467ffffffffffffffff191690555050565b60001960ff8316016115f25780156115f2576040516307b8c74d60e51b815260040160405180910390fd5b600081815260018301602052604081205461349b57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d59565b506000610d59565b81518051606080850151908301516080808701519401516040516000958695889561350795919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a0015160405160200161354a9190615d3e565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b6000806135b98585856138fe565b6001600160401b0387166000908152600a6020908152604080832093835292905220549150505b949350505050565b600060026135f760808561561c565b6001600160401b031661360a9190615642565b905060006136188585611cca565b905081613627600160046155f3565b901b19168183600381111561363e5761363e61425c565b6001600160401b03871660009081526009602052604081209190921b9290921791829161366c60808861598b565b6001600160401b031681526020810191909152604001600020555050505050565b604051630304c3e160e51b815260009060609030906360987c20906136ba90889088908890600401615dd5565b600060405180830381600087803b1580156136d457600080fd5b505af19250505080156136e5575060015b613724573d808015613713576040519150601f19603f3d011682016040523d82523d6000602084013e613718565b606091505b50600392509050613739565b50506040805160208101909152600081526002905b935093915050565b60008060008060006137a28860405160240161376c91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b17905288886113886084613824565b925092509250826137c8578160405163e1cd550960e01b81526004016107c29190613f8c565b60208251146137f7578151604051631e3be00960e21b81526020600482015260248101919091526044016107c2565b8180602001905181019061380b9190615c84565b61381582886155f3565b94509450505050935093915050565b6000606060008361ffff166001600160401b0381111561384657613846613c3e565b6040519080825280601f01601f191660200182016040528015613870576020820181803683370190505b509150863b61388a5763030ed58f60e21b60005260046000fd5b5a858110156138a457632be8ca8b60e21b60005260046000fd5b85900360408104810387106138c4576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156138e75750835b808352806000602085013e50955095509592505050565b825182516000919081830361392657604051630469ac9960e21b815260040160405180910390fd5b610101821180159061393a57506101018111155b613957576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613981576040516309bde33960e01b815260040160405180910390fd5b806000036139ae578660008151811061399c5761399c615309565b60200260200101519350505050613b7c565b6000816001600160401b038111156139c8576139c8613c3e565b6040519080825280602002602001820160405280156139f1578160200160208202803683370190505b50905060008080805b85811015613b1b5760006001821b8b811603613a555788851015613a3e578c5160018601958e918110613a2f57613a2f615309565b60200260200101519050613a77565b8551600185019487918110613a2f57613a2f615309565b8b5160018401938d918110613a6c57613a6c615309565b602002602001015190505b600089861015613aa7578d5160018701968f918110613a9857613a98615309565b60200260200101519050613ac9565b8651600186019588918110613abe57613abe615309565b602002602001015190505b82851115613aea576040516309bde33960e01b815260040160405180910390fd5b613af48282613b83565b878481518110613b0657613b06615309565b602090810291909101015250506001016139fa565b506001850382148015613b2d57508683145b8015613b3857508581145b613b55576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613b6a57613b6a615309565b60200260200101519750505050505050505b9392505050565b6000818310613b9b57613b968284613ba1565b610d56565b610d5683835b60408051600160208201529081018390526060810182905260009060800161358d565b828054828255906000526020600020908101928215613c19579160200282015b82811115613c1957825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613be4565b50613c25929150613c29565b5090565b5b80821115613c255760008155600101613c2a565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613c7657613c76613c3e565b60405290565b60405160a081016001600160401b0381118282101715613c7657613c76613c3e565b60405160c081016001600160401b0381118282101715613c7657613c76613c3e565b604080519081016001600160401b0381118282101715613c7657613c76613c3e565b604051606081016001600160401b0381118282101715613c7657613c76613c3e565b604051601f8201601f191681016001600160401b0381118282101715613d2c57613d2c613c3e565b604052919050565b60006001600160401b03821115613d4d57613d4d613c3e565b5060051b60200190565b6001600160a01b038116811461052f57600080fd5b80356001600160401b0381168114613d8357600080fd5b919050565b801515811461052f57600080fd5b8035613d8381613d88565b60006001600160401b03821115613dba57613dba613c3e565b50601f01601f191660200190565b600082601f830112613dd957600080fd5b8135613dec613de782613da1565b613d04565b818152846020838601011115613e0157600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613e3157600080fd5b82356001600160401b0380821115613e4857600080fd5b818501915085601f830112613e5c57600080fd5b8135613e6a613de782613d34565b81815260059190911b83018401908481019088831115613e8957600080fd5b8585015b83811015613f2f57803585811115613ea55760008081fd5b86016080818c03601f1901811315613ebd5760008081fd5b613ec5613c54565b89830135613ed281613d57565b81526040613ee1848201613d6c565b8b830152606080850135613ef481613d88565b83830152928401359289841115613f0d57600091508182fd5b613f1b8f8d86880101613dc8565b908301525085525050918601918601613e8d565b5098975050505050505050565b60005b83811015613f57578181015183820152602001613f3f565b50506000910152565b60008151808452613f78816020860160208601613f3c565b601f01601f19169290920160200192915050565b602081526000610d566020830184613f60565b8060608101831015610d5957600080fd5b60008083601f840112613fc257600080fd5b5081356001600160401b03811115613fd957600080fd5b602083019150836020828501011115613ff157600080fd5b9250929050565b60008083601f84011261400a57600080fd5b5081356001600160401b0381111561402157600080fd5b6020830191508360208260051b8501011115613ff157600080fd5b60008060008060008060008060e0898b03121561405857600080fd5b6140628a8a613f9f565b975060608901356001600160401b038082111561407e57600080fd5b61408a8c838d01613fb0565b909950975060808b01359150808211156140a357600080fd5b6140af8c838d01613ff8565b909750955060a08b01359150808211156140c857600080fd5b506140d58b828c01613ff8565b999c989b50969995989497949560c00135949350505050565b60008060006080848603121561410357600080fd5b61410d8585613f9f565b925060608401356001600160401b0381111561412857600080fd5b61413486828701613fb0565b9497909650939450505050565b6001600160a01b0381511682526020810151151560208301526001600160401b03604082015116604083015260006060820151608060608501526135e06080850182613f60565b604080825283519082018190526000906020906060840190828701845b828110156141ca5781516001600160401b0316845292840192908401906001016141a5565b50505083810382850152845180825282820190600581901b8301840187850160005b8381101561421a57601f19868403018552614208838351614141565b948701949250908601906001016141ec565b50909998505050505050505050565b6000806040838503121561423c57600080fd5b61424583613d6c565b915061425360208401613d6c565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b600481106142825761428261425c565b9052565b60208101610d598284614272565b600060a082840312156142a657600080fd5b6142ae613c7c565b9050813581526142c060208301613d6c565b60208201526142d160408301613d6c565b60408201526142e260608301613d6c565b60608201526142f360808301613d6c565b608082015292915050565b8035613d8381613d57565b803563ffffffff81168114613d8357600080fd5b600082601f83011261432e57600080fd5b8135602061433e613de783613d34565b82815260059290921b8401810191818101908684111561435d57600080fd5b8286015b8481101561442d5780356001600160401b03808211156143815760008081fd5b9088019060a0828b03601f190181131561439b5760008081fd5b6143a3613c7c565b87840135838111156143b55760008081fd5b6143c38d8a83880101613dc8565b8252506040808501356143d581613d57565b828a015260606143e6868201614309565b828401526080915081860135858111156144005760008081fd5b61440e8f8c838a0101613dc8565b9184019190915250919093013590830152508352918301918301614361565b509695505050505050565b6000610140828403121561444b57600080fd5b614453613c9e565b905061445f8383614294565b815260a08201356001600160401b038082111561447b57600080fd5b61448785838601613dc8565b602084015260c08401359150808211156144a057600080fd5b6144ac85838601613dc8565b60408401526144bd60e085016142fe565b606084015261010084013560808401526101208401359150808211156144e257600080fd5b506144ef8482850161431d565b60a08301525092915050565b600082601f83011261450c57600080fd5b8135602061451c613de783613d34565b82815260059290921b8401810191818101908684111561453b57600080fd5b8286015b8481101561442d5780356001600160401b0381111561455e5760008081fd5b61456c8986838b0101614438565b84525091830191830161453f565b600082601f83011261458b57600080fd5b8135602061459b613de783613d34565b82815260059290921b840181019181810190868411156145ba57600080fd5b8286015b8481101561442d5780356001600160401b03808211156145dd57600080fd5b818901915089603f8301126145f157600080fd5b85820135614601613de782613d34565b81815260059190911b830160400190878101908c83111561462157600080fd5b604085015b8381101561465a5780358581111561463d57600080fd5b61464c8f6040838a0101613dc8565b845250918901918901614626565b508752505050928401925083016145be565b600082601f83011261467d57600080fd5b8135602061468d613de783613d34565b8083825260208201915060208460051b8701019350868411156146af57600080fd5b602086015b8481101561442d57803583529183019183016146b4565b600082601f8301126146dc57600080fd5b813560206146ec613de783613d34565b82815260059290921b8401810191818101908684111561470b57600080fd5b8286015b8481101561442d5780356001600160401b038082111561472f5760008081fd5b9088019060a0828b03601f19018113156147495760008081fd5b614751613c7c565b61475c888501613d6c565b8152604080850135848111156147725760008081fd5b6147808e8b838901016144fb565b8a84015250606080860135858111156147995760008081fd5b6147a78f8c838a010161457a565b83850152506080915081860135858111156147c25760008081fd5b6147d08f8c838a010161466c565b918401919091525091909301359083015250835291830191830161470f565b6000806040838503121561480257600080fd5b6001600160401b038335111561481757600080fd5b61482484843585016146cb565b91506001600160401b036020840135111561483e57600080fd5b6020830135830184601f82011261485457600080fd5b614861613de78235613d34565b81358082526020808301929160051b84010187101561487f57600080fd5b602083015b6020843560051b850101811015614a25576001600160401b03813511156148aa57600080fd5b87603f8235860101126148bc57600080fd5b6148cf613de76020833587010135613d34565b81358501602081810135808452908301929160059190911b016040018a10156148f757600080fd5b604083358701015b83358701602081013560051b01604001811015614a15576001600160401b038135111561492b57600080fd5b833587018135016040818d03603f1901121561494657600080fd5b61494e613cc0565b604082013581526001600160401b036060830135111561496d57600080fd5b8c605f60608401358401011261498257600080fd5b6040606083013583010135614999613de782613d34565b808282526020820191508f60608460051b60608801358801010111156149be57600080fd5b6060808601358601015b60608460051b6060880135880101018110156149f5576149e781614309565b8352602092830192016149c8565b5080602085015250505080855250506020830192506020810190506148ff565b5084525060209283019201614884565b508093505050509250929050565b600080600080600060608688031215614a4b57600080fd5b85356001600160401b0380821115614a6257600080fd5b614a6e89838a01614438565b96506020880135915080821115614a8457600080fd5b614a9089838a01613ff8565b90965094506040880135915080821115614aa957600080fd5b50614ab688828901613ff8565b969995985093965092949392505050565b600060808284031215614ad957600080fd5b614ae1613c54565b8235614aec81613d57565b8152614afa60208401614309565b60208201526040830135614b0d81613d88565b60408201526060830135614b2081613d57565b60608201529392505050565b600060208284031215614b3e57600080fd5b81356001600160401b03811115614b5457600080fd5b820160a08185031215613b7c57600080fd5b803560ff81168114613d8357600080fd5b600060208284031215614b8957600080fd5b610d5682614b66565b60008151808452602080850194506020840160005b83811015614bcc5781516001600160a01b031687529582019590820190600101614ba7565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c2660e0840182614b92565b90506040840151601f198483030160c0850152614c438282614b92565b95945050505050565b60008060408385031215614c5f57600080fd5b614c6883613d6c565b946020939093013593505050565b600060208284031215614c8857600080fd5b610d5682613d6c565b602081526000610d566020830184614141565b600060208284031215614cb657600080fd5b8135613b7c81613d57565b600082601f830112614cd257600080fd5b81356020614ce2613de783613d34565b8083825260208201915060208460051b870101935086841115614d0457600080fd5b602086015b8481101561442d578035614d1c81613d57565b8352918301918301614d09565b60006020808385031215614d3c57600080fd5b82356001600160401b0380821115614d5357600080fd5b818501915085601f830112614d6757600080fd5b8135614d75613de782613d34565b81815260059190911b83018401908481019088831115614d9457600080fd5b8585015b83811015613f2f57803585811115614daf57600080fd5b860160c0818c03601f19011215614dc65760008081fd5b614dce613c9e565b8882013581526040614de1818401614b66565b8a8301526060614df2818501614b66565b8284015260809150614e05828501613d96565b9083015260a08381013589811115614e1d5760008081fd5b614e2b8f8d83880101614cc1565b838501525060c0840135915088821115614e455760008081fd5b614e538e8c84870101614cc1565b9083015250845250918601918601614d98565b80356001600160e01b0381168114613d8357600080fd5b600082601f830112614e8e57600080fd5b81356020614e9e613de783613d34565b82815260069290921b84018101918181019086841115614ebd57600080fd5b8286015b8481101561442d5760408189031215614eda5760008081fd5b614ee2613cc0565b614eeb82613d6c565b8152614ef8858301614e66565b81860152835291830191604001614ec1565b600082601f830112614f1b57600080fd5b81356020614f2b613de783613d34565b82815260059290921b84018101918181019086841115614f4a57600080fd5b8286015b8481101561442d5780356001600160401b0380821115614f6e5760008081fd5b9088019060a0828b03601f1901811315614f885760008081fd5b614f90613c7c565b614f9b888501613d6c565b815260408085013584811115614fb15760008081fd5b614fbf8e8b83890101613dc8565b8a8401525060609350614fd3848601613d6c565b908201526080614fe4858201613d6c565b93820193909352920135908201528352918301918301614f4e565b600082601f83011261501057600080fd5b81356020615020613de783613d34565b82815260069290921b8401810191818101908684111561503f57600080fd5b8286015b8481101561442d576040818903121561505c5760008081fd5b615064613cc0565b813581528482013585820152835291830191604001615043565b6000602080838503121561509157600080fd5b82356001600160401b03808211156150a857600080fd5b90840190606082870312156150bc57600080fd5b6150c4613ce2565b8235828111156150d357600080fd5b830160408189038113156150e657600080fd5b6150ee613cc0565b8235858111156150fd57600080fd5b8301601f81018b1361510e57600080fd5b803561511c613de782613d34565b81815260069190911b8201890190898101908d83111561513b57600080fd5b928a01925b8284101561518b5785848f0312156151585760008081fd5b615160613cc0565b843561516b81613d57565b8152615178858d01614e66565b818d0152825292850192908a0190615140565b8452505050828701359150848211156151a357600080fd5b6151af8a838501614e7d565b818801528352505082840135828111156151c857600080fd5b6151d488828601614f0a565b858301525060408301359350818411156151ed57600080fd5b6151f987858501614fff565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561529957601f19868403018952815160a06001600160401b0380835116865286830151828888015261525d83880182613f60565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101615225565b5090979650505050505050565b6001600160a01b0384168152600060206060818401526152c96060840186615208565b83810360408581019190915285518083528387019284019060005b8181101561421a578451805184528601518684015293850193918301916001016152e4565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561537657835180516001600160a01b031684528501516001600160e01b031685840152928401929185019160010161533f565b50508583015187820388850152805180835290840192506000918401905b808310156153cf57835180516001600160401b031683528501516001600160e01b031685830152928401926001929092019190850190615394565b50979650505050505050565b602081526000610d56602083018461531f565b60006020828403121561540057600080fd5b8151613b7c81613d88565b600181811c9082168061541f57607f821691505b60208210810361543f57634e487b7160e01b600052602260045260246000fd5b50919050565b60008083546154538161540b565b6001828116801561546b5760018114615480576154af565b60ff19841687528215158302870194506154af565b8760005260208060002060005b858110156154a65781548a82015290840190820161548d565b50505082870194505b50929695505050505050565b600081546154c88161540b565b8085526020600183811680156154e557600181146154ff5761552d565b60ff1985168884015283151560051b88018301955061552d565b866000528260002060005b858110156155255781548a820186015290830190840161550a565b890184019650505b505050505092915050565b60408152600061554b6040830185613f60565b8281036020840152614c4381856154bb565b634e487b7160e01b600052601160045260246000fd5b6001600160401b038181168382160190808211156155935761559361555d565b5092915050565b6040815260006155ad6040830185615208565b8281036020840152614c43818561531f565b6000602082840312156155d157600080fd5b81356001600160401b038111156155e757600080fd5b6135e0848285016146cb565b81810381811115610d5957610d5961555d565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061563657615636615606565b92169190910692915050565b8082028115828204841417610d5957610d5961555d565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261568c60a0870182613f60565b9050606085015186820360608801526156a58282613f60565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156153cf57835180516001600160a01b03168352860151868301529285019260019290920191908401906156c8565b602081526000610d566020830184615659565b6080815260006157206080830187615659565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561575e57600080fd5b835161576981613d88565b60208501519093506001600160401b0381111561578557600080fd5b8401601f8101861361579657600080fd5b80516157a4613de782613da1565b8181528760208385010111156157b957600080fd5b6157ca826020830160208601613f3c565b809450505050604084015190509250925092565b601f821115610fe9576000816000526020600020601f850160051c810160208610156158075750805b601f850160051c820191505b8181101561582657828155600101615813565b505050505050565b81516001600160401b0381111561584757615847613c3e565b61585b81615855845461540b565b846157de565b602080601f83116001811461589057600084156158785750858301515b600019600386901b1c1916600185901b178555615826565b600085815260208120601f198616915b828110156158bf578886015182559484019460019091019084016158a0565b50858210156158dd5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610d5660a08301600185016154bb565b80820180821115610d5957610d5961555d565b60ff8181168382160190811115610d5957610d5961555d565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b03808416806159a5576159a5615606565b92169190910492915050565b6000602082840312156159c357600080fd5b610d5682614309565b6000808335601e198436030181126159e357600080fd5b8301803591506001600160401b038211156159fd57600080fd5b602001915036819003821315613ff157600080fd5b6020810160068310615a2657615a2661425c565b91905290565b60ff81811683821602908116908181146155935761559361555d565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615aa05784546001600160a01b031683526001948501949284019201615a7b565b50508481036060860152865180825290820192508187019060005b81811015615ae05782516001600160a01b031685529383019391830191600101615abb565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b03808616835280851660208401525060606040830152614c436060830184613f60565b8281526040602082015260006135e06040830184613f60565b6001600160401b03848116825283166020820152606081016135e06040830184614272565b848152615b746020820185614272565b608060408201526000615b8a6080830185613f60565b905082606083015295945050505050565b600060208284031215615bad57600080fd5b8151613b7c81613d57565b6020815260008251610100806020850152615bd7610120850183613f60565b91506020850151615bf360408601826001600160401b03169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c2d60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c4a8483613f60565b935060c08701519150808685030160e0870152615c678483613f60565b935060e0870151915080868503018387015250615af08382613f60565b600060208284031215615c9657600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b8481101561529957601f19868403018952815160a08151818652615ce082870182613f60565b9150506001600160a01b03868301511686860152604063ffffffff8184015116818701525060608083015186830382880152615d1c8382613f60565b6080948501519790940196909652505098840198925090830190600101615cba565b602081526000610d566020830184615c9d565b60008282518085526020808601955060208260051b8401016020860160005b8481101561529957601f19868403018952615d8c838351613f60565b98840198925090830190600101615d70565b60008151808452602080850194506020840160005b83811015614bcc57815163ffffffff1687529582019590820190600101615db3565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615e3d6101a0850183613f60565b91506040870151605f198086850301610120870152615e5c8483613f60565b935060608901519150615e79838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615ea28282615c9d565b9150508281036020840152615eb78186615d51565b90508281036040840152615af08185615d9e56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyBatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationNotAllowedInExecutionPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationRequiredInCommitPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllSourceChainConfigs\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReport[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006be738038062006be7833981016040819052620000359162000880565b336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620001c4565b50504660805260208301516001600160a01b03161580620000b6575060408301516001600160a01b0316155b80620000cd575060608301516001600160a01b0316155b15620000ec576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b0316600003620001185760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001b0826200023e565b620001bb816200032c565b50505062000c72565b336001600160a01b03821603620001ee57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b031662000267576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516001600160a01b039889166001600160c01b03199097168717600160a01b63ffffffff958616021760ff60c01b1916600160c01b911515919091021790965560608089018051600580546001600160a01b031916918b169190911790558251968752935190921693850193909352935115159183019190915251909216908201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9060800160405180910390a150565b60005b8151811015620005c1576000828281518110620003505762000350620009aa565b60200260200101519050600081602001519050806001600160401b03166000036200038e5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003b7576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526008602052604090206060830151600182018054620003e590620009c0565b905060000362000448578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004b9565b8154600160a81b90046001600160401b03166001148015906200048b57508051602082012060405162000480906001850190620009fc565b604051809103902014155b15620004b957604051632105803760e11b81526001600160401b038416600482015260240160405180910390fd5b80511580620004ef5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200050e576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200051e828262000acf565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b0319909116171782556200056d60066001600160401b038516620005c5565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b83604051620005a9919062000b9b565b60405180910390a2505050508060010190506200032f565b5050565b6000620005d38383620005dc565b90505b92915050565b60008181526001830160205260408120546200062557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620005d6565b506000620005d6565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200066957620006696200062e565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200069a576200069a6200062e565b604052919050565b80516001600160401b0381168114620006ba57600080fd5b919050565b6001600160a01b0381168114620006d557600080fd5b50565b80518015158114620006ba57600080fd5b6000601f83601f840112620006fd57600080fd5b825160206001600160401b03808311156200071c576200071c6200062e565b8260051b6200072d8382016200066f565b93845286810183019383810190898611156200074857600080fd5b84890192505b858310156200087357825184811115620007685760008081fd5b89016080601f19828d038101821315620007825760008081fd5b6200078c62000644565b888401516200079b81620006bf565b81526040620007ac858201620006a2565b8a8301526060620007bf818701620006d8565b83830152938501519389851115620007d75760008081fd5b84860195508f603f870112620007ef57600094508485fd5b8a8601519450898511156200080857620008086200062e565b620008198b858f880116016200066f565b93508484528f82868801011115620008315760008081fd5b60005b8581101562000851578681018301518582018d01528b0162000834565b5060009484018b0194909452509182015283525091840191908401906200074e565b9998505050505050505050565b60008060008385036101208112156200089857600080fd5b6080811215620008a757600080fd5b620008b162000644565b620008bc86620006a2565b81526020860151620008ce81620006bf565b60208201526040860151620008e381620006bf565b60408201526060860151620008f881620006bf565b606082015293506080607f19820112156200091257600080fd5b506200091d62000644565b60808501516200092d81620006bf565b815260a085015163ffffffff811681146200094757600080fd5b60208201526200095a60c08601620006d8565b604082015260e08501516200096f81620006bf565b60608201526101008501519092506001600160401b038111156200099257600080fd5b620009a086828701620006e9565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680620009d557607f821691505b602082108103620009f657634e487b7160e01b600052602260045260246000fd5b50919050565b600080835462000a0c81620009c0565b6001828116801562000a27576001811462000a3d5762000a6e565b60ff198416875282151583028701945062000a6e565b8760005260208060002060005b8581101562000a655781548a82015290840190820162000a4a565b50505082870194505b50929695505050505050565b601f82111562000aca576000816000526020600020601f850160051c8101602086101562000aa55750805b601f850160051c820191505b8181101562000ac65782815560010162000ab1565b5050505b505050565b81516001600160401b0381111562000aeb5762000aeb6200062e565b62000b038162000afc8454620009c0565b8462000a7a565b602080601f83116001811462000b3b576000841562000b225750858301515b600019600386901b1c1916600185901b17855562000ac6565b600085815260208120601f198616915b8281101562000b6c5788860151825594840194600190910190840162000b4b565b508582101562000b8b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000bf081620009c0565b8060a089015260c0600183166000811462000c14576001811462000c315762000c63565b60ff19841660c08b015260c083151560051b8b0101945062000c63565b85600052602060002060005b8481101562000c5a5781548c820185015290880190890162000c3d565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615ef862000cef600039600081816102070152612a4a0152600081816101d80152612cf20152600081816101a901528181610f7501528181611125015261244a01526000818161017a015281816125f501526126ac01526000818161190401526119370152615ef86000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80637edf52f4116100ad578063de5e0b9a11610071578063de5e0b9a146104b2578063e9d68a8e146104c5578063f2fde38b146104e5578063f58e03fc146104f8578063f716f99f1461050b57600080fd5b80637edf52f41461041257806385572ffb146104255780638da5cb5b14610433578063c673e5841461044e578063ccd37ba31461046e57600080fd5b80635e36480c116100f45780635e36480c146103075780635e7bb0081461032757806360987c201461033a5780637437ff9f1461034d57806379ba50971461040a57600080fd5b806304666f9c1461013157806306285c6914610146578063181f5a771461028d5780633f4b04aa146102d65780635215505b146102f1575b600080fd5b61014461013f366004613e1c565b61051e565b005b61023760408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b604051610284919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102c96040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102849190613f8a565b600b546040516001600160401b039091168152602001610284565b6102f9610532565b604051610284929190613fe4565b61031a610315366004614085565b61078d565b60405161028491906140e2565b61014461033536600461464b565b6107e2565b6101446103483660046148da565b610a76565b6103c360408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526004546001600160a01b038082168352600160a01b820463ffffffff166020840152600160c01b90910460ff16151592820192909252600554909116606082015290565b604051610284919081516001600160a01b03908116825260208084015163ffffffff1690830152604080840151151590830152606092830151169181019190915260800190565b610144610d33565b61014461042036600461496e565b610db6565b61014461012c3660046149d3565b6001546040516001600160a01b039091168152602001610284565b61046161045c366004614a1e565b610dc7565b6040516102849190614a7e565b6104a461047c366004614af3565b6001600160401b03919091166000908152600a60209081526040808320938352929052205490565b604051908152602001610284565b6101446104c0366004614b6f565b610f25565b6104d86104d3366004614c21565b611428565b6040516102849190614c3c565b6101446104f3366004614c4f565b611534565b610144610506366004614c6c565b611545565b610144610519366004614d27565b6115ae565b6105266115f0565b61052f8161161d565b50565b606080600061054160066118a6565b6001600160401b0381111561055857610558613c3c565b6040519080825280602002602001820160405280156105a957816020015b60408051608081018252600080825260208083018290529282015260608082015282526000199092019101816105765790505b50905060006105b860066118a6565b6001600160401b038111156105cf576105cf613c3c565b6040519080825280602002602001820160405280156105f8578160200160208202803683370190505b50905060005b61060860066118a6565b8110156107845761061a6006826118b0565b82828151811061062c5761062c614e64565b60200260200101906001600160401b031690816001600160401b0316815250506008600083838151811061066257610662614e64565b6020908102919091018101516001600160401b039081168352828201939093526040918201600020825160808101845281546001600160a01b038116825260ff600160a01b820416151593820193909352600160a81b909204909316918101919091526001820180549192916060840191906106dd90614e7a565b80601f016020809104026020016040519081016040528092919081815260200182805461070990614e7a565b80156107565780601f1061072b57610100808354040283529160200191610756565b820191906000526020600020905b81548152906001019060200180831161073957829003601f168201915b50505050508152505083828151811061077157610771614e64565b60209081029190910101526001016105fe565b50939092509050565b600061079b60016004614eca565b60026107a8608085614ef3565b6001600160401b03166107bb9190614f19565b6107c585856118bc565b901c1660038111156107d9576107d96140b8565b90505b92915050565b6107ea611901565b81518151811461080d576040516320f8fd5960e21b815260040160405180910390fd5b60005b81811015610a6657600084828151811061082c5761082c614e64565b6020026020010151905060008160200151519050600085848151811061085457610854614e64565b602002602001015190508051821461087f576040516320f8fd5960e21b815260040160405180910390fd5b60005b82811015610a5757600082828151811061089e5761089e614e64565b60200260200101516000015190506000856020015183815181106108c4576108c4614e64565b602002602001015190508160001461091d57806080015182101561091d578551815151604051633a98d46360e11b81526001600160401b0390921660048301526024820152604481018390526064015b60405180910390fd5b83838151811061092f5761092f614e64565b602002602001015160200151518160a00151511461097c57805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b03166024820152604401610914565b60005b8160a0015151811015610a495760008585815181106109a0576109a0614e64565b60200260200101516020015182815181106109bd576109bd614e64565b602002602001015163ffffffff16905080600014610a405760008360a0015183815181106109ed576109ed614e64565b60200260200101516040015163ffffffff16905080821015610a3e578351516040516348e617b360e01b81526004810191909152602481018490526044810182905260648101839052608401610914565b505b5060010161097f565b505050806001019050610882565b50505050806001019050610810565b50610a718383611969565b505050565b333014610a96576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610ad3565b6040805180820190915260008082526020820152815260200190600190039081610aac5790505b5060a08701515190915015610b0957610b068660a001518760200151886060015189600001516020015189898989611a2c565b90505b6040805160a081018252875151815287516020908101516001600160401b03168183015288015181830152908701516060820152608081018290526005546001600160a01b03168015610bfc576040516308d450a160e01b81526001600160a01b038216906308d450a190610b82908590600401614fdd565b600060405180830381600087803b158015610b9c57600080fd5b505af1925050508015610bad575060015b610bfc573d808015610bdb576040519150601f19603f3d011682016040523d82523d6000602084013e610be0565b606091505b50806040516309c2532560e01b81526004016109149190613f8a565b604088015151158015610c1157506080880151155b80610c28575060608801516001600160a01b03163b155b80610c4f57506060880151610c4d906001600160a01b03166385572ffb60e01b611bdd565b155b15610c5c57505050610d2c565b87516020908101516001600160401b03166000908152600890915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610cba9289926113889291600401614ff0565b6000604051808303816000875af1158015610cd9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d01919081019061502c565b509150915081610d2657806040516302a35ba360e21b81526004016109149190613f8a565b50505050505b5050505050565b6000546001600160a01b03163314610d5e5760405163015aa1e360e11b815260040160405180910390fd5b600180546001600160a01b0319808216339081179093556000805490911681556040516001600160a01b03909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610dbe6115f0565b61052f81611bf9565b610e0a6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610eb357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e95575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610f1557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ef7575b5050505050815250509050919050565b6000610f33878901896152d9565b6004805491925090600160c01b900460ff16610fdd5760208201515115610fdd5760208201516040808401519051633854844f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926370a9089e92610fac9230929190600401615501565b60006040518083038186803b158015610fc457600080fd5b505afa158015610fd8573d6000803e3d6000fd5b505050505b81515151151580610ff357508151602001515115155b156110be57600b5460208b0135906001600160401b038083169116101561109657600b805467ffffffffffffffff19166001600160401b03831617905581548351604051633937306f60e01b81526001600160a01b0390921691633937306f9161105f91600401615614565b600060405180830381600087803b15801561107957600080fd5b505af115801561108d573d6000803e3d6000fd5b505050506110bc565b8260200151516000036110bc57604051632261116760e01b815260040160405180910390fd5b505b60005b826020015151811015611374576000836020015182815181106110e6576110e6614e64565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561116c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111909190615627565b156111b957604051637edeb53960e11b81526001600160401b0382166004820152602401610914565b60006111c482611cfe565b9050806001016040516111d79190615644565b6040518091039020836020015180519060200120146112145782602001518160010160405163b80d8fa960e01b8152600401610914929190615737565b60408301518154600160a81b90046001600160401b039081169116141580611255575082606001516001600160401b031683604001516001600160401b0316115b1561129a57825160408085015160608601519151636af0786b60e11b81526001600160401b039384166004820152908316602482015291166044820152606401610914565b6080830151806112bd5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600a60209081526040808320848452909152902054156113155783516040516332cf0cbf60e01b81526001600160401b03909116600482015260248101829052604401610914565b606084015161132590600161575c565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600a6020908152604080832094835293905291909120429055506001016110c1565b50602082015182516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e4926113ac929091615783565b60405180910390a1610d2660008b8b8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d9182918501908490808284376000920191909152508c9250611d4a915050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260088352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916114b490614e7a565b80601f01602080910402602001604051908101604052809291908181526020018280546114e090614e7a565b8015610f155780601f1061150257610100808354040283529160200191610f15565b820191906000526020600020905b81548152906001019060200180831161151057505050919092525091949350505050565b61153c6115f0565b61052f81612043565b611585611554828401846157a8565b604080516000808252602082019092529061157f565b606081526020019060019003908161156a5790505b50611969565b6040805160008082526020820190925290506115a8600185858585866000611d4a565b50505050565b6115b66115f0565b60005b81518110156115ec576115e48282815181106115d7576115d7614e64565b60200260200101516120bc565b6001016115b9565b5050565b6001546001600160a01b0316331461161b576040516315ae3a6f60e11b815260040160405180910390fd5b565b60005b81518110156115ec57600082828151811061163d5761163d614e64565b60200260200101519050600081602001519050806001600160401b031660000361167a5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166116a2576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260086020526040902060608301516001820180546116ce90614e7a565b905060000361173057815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611799565b8154600160a81b90046001600160401b0316600114801590611770575080516020820120604051611765906001850190615644565b604051809103902014155b1561179957604051632105803760e11b81526001600160401b0384166004820152602401610914565b805115806117ce5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156117ec576040516342bcdf7f60e11b815260040160405180910390fd5b600182016117fa828261582c565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b029290921674ffffffffffffffffffffffffffffffffffffffffff199091161717825561185560066001600160401b0385166123e6565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b8360405161188f91906158eb565b60405180910390a250505050806001019050611620565b60006107dc825490565b60006107d983836123f2565b6001600160401b0382166000908152600960205260408120816118e0608085615939565b6001600160401b031681526020810191909152604001600020549392505050565b467f00000000000000000000000000000000000000000000000000000000000000001461161b57604051630f01ce8560e01b81527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610914565b815160000361198b5760405163c2e5347d60e01b815260040160405180910390fd5b805160408051600080825260208201909252911591816119ce565b6040805180820190915260008152606060208201528152602001906001900390816119a65790505b50905060005b8451811015610d2c57611a248582815181106119f2576119f2614e64565b602002602001015184611a1e57858381518110611a1157611a11614e64565b602002602001015161241c565b8361241c565b6001016119d4565b606088516001600160401b03811115611a4757611a47613c3c565b604051908082528060200260200182016040528015611a8c57816020015b6040805180820190915260008082526020820152815260200190600190039081611a655790505b509050811560005b8a51811015611bcf5781611b2c57848482818110611ab457611ab4614e64565b9050602002016020810190611ac9919061595f565b63ffffffff1615611b2c57848482818110611ae657611ae6614e64565b9050602002016020810190611afb919061595f565b8b8281518110611b0d57611b0d614e64565b60200260200101516040019063ffffffff16908163ffffffff16815250505b611baa8b8281518110611b4157611b41614e64565b60200260200101518b8b8b8b8b87818110611b5e57611b5e614e64565b9050602002810190611b70919061597a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612cb792505050565b838281518110611bbc57611bbc614e64565b6020908102919091010152600101611a94565b505098975050505050505050565b6000611be883612f99565b80156107d957506107d98383612fcc565b80516001600160a01b0316611c21576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516001600160a01b039889167fffffffffffffffff0000000000000000000000000000000000000000000000009097168717600160a01b63ffffffff958616021760ff60c01b1916600160c01b911515919091021790965560608089018051600580546001600160a01b031916918b169190911790558251968752935190921693850193909352935115159183019190915251909216908201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9060800160405180910390a150565b6001600160401b03811660009081526008602052604081208054600160a01b900460ff166107dc5760405163ed053c5960e01b81526001600160401b0384166004820152602401610914565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611da98760846159c0565b9050826060015115611df1578451611dc2906020614f19565b8651611dcf906020614f19565b611dda9060a06159c0565b611de491906159c0565b611dee90826159c0565b90505b368114611e1a57604051638e1192e160e01b815260048101829052366024820152604401610914565b5081518114611e495781516040516324f7d61360e21b8152600481019190915260248101829052604401610914565b611e51611901565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611e9f57611e9f6140b8565b6002811115611eb057611eb06140b8565b9052509050600281602001516002811115611ecd57611ecd6140b8565b148015611f215750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611f0957611f09614e64565b6000918252602090912001546001600160a01b031633145b611f3e57604051631b41e11d60e31b815260040160405180910390fd5b50816060015115611fee576020820151611f599060016159d3565b60ff16855114611f7c576040516371253a2560e01b815260040160405180910390fd5b8351855114611f9e5760405163a75d88af60e01b815260040160405180910390fd5b60008787604051611fb09291906159ec565b604051908190038120611fc7918b906020016159fc565b604051602081830303815290604052805190602001209050611fec8a82888888613056565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b336001600160a01b0382160361206c57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120e7576000604051631b3fab5160e11b81526004016109149190615a10565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003612138576060840151600182018054911515620100000262ff000019909216919091179055612174565b6060840151600182015460ff6201000090910416151590151514612174576040516321fd80df60e21b815260ff84166004820152602401610914565b60a0840151805161010010156121a0576001604051631b3fab5160e11b81526004016109149190615a10565b80516000036121c5576005604051631b3fab5160e11b81526004016109149190615a10565b61222b848460030180548060200260200160405190810160405280929190818152602001828054801561222157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612203575b5050505050613209565b84606001511561235b576122998484600201805480602002602001604051908101604052809291908181526020018280548015612221576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311612203575050505050613209565b6080850151805161010010156122c5576002604051631b3fab5160e11b81526004016109149190615a10565b60408601516122d5906003615a2a565b60ff168151116122fb576003604051631b3fab5160e11b81526004016109149190615a10565b815181511015612321576001604051631b3fab5160e11b81526004016109149190615a10565b805160018401805461ff00191661010060ff84160217905561234c9060028601906020840190613bc2565b5061235985826001613272565b505b61236784826002613272565b805161237c9060038501906020840190613bc2565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123d59389939260028a01929190615a46565b60405180910390a1610d2c846133cd565b60006107d98383613450565b600082600001828154811061240957612409614e64565b9060005260206000200154905092915050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124bd9190615627565b1561252e5780156124ec57604051637edeb53960e11b81526001600160401b0383166004820152602401610914565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b602084015151600081900361256457845160405163676cf24b60e11b81526001600160401b039091166004820152602401610914565b8460400151518114612589576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b038111156125a3576125a3613c3c565b6040519080825280602002602001820160405280156125cc578160200160208202803683370190505b50905060007f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f857f000000000000000000000000000000000000000000000000000000000000000061261d88611cfe565b60010160405161262d9190615644565b604051908190038120612665949392916020019384526001600160401b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120905060005b8381101561279b576000886020015182815181106126a0576126a0614e64565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146127175780516040908101519051631c21951160e11b81526001600160401b039091166004820152602401610914565b866001600160401b03168160000151602001516001600160401b03161461276b57805160200151604051636c95f1eb60e01b81526001600160401b03808a1660048301529091166024820152604401610914565b612775818461349f565b84838151811061278757612787614e64565b602090810291909101015250600101612680565b505060006127b3858389606001518a608001516135a7565b9050806000036127e157604051633ee8bd3f60e11b81526001600160401b0386166004820152602401610914565b60005b83811015612cad5760005a905060008960200151838151811061280957612809614e64565b6020026020010151905060006128278983600001516060015161078d565b9050600081600381111561283d5761283d6140b8565b148061285a57506003816003811115612858576128586140b8565b145b6128b057815160600151604080516001600160401b03808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612ca5565b6060881561298f578a85815181106128ca576128ca614e64565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff166128f88842614eca565b119050808061291857506003836003811115612916576129166140b8565b145b612940576040516354e7e43160e11b81526001600160401b038c166004820152602401610914565b8b868151811061295257612952614e64565b602002602001015160000151600014612989578b868151811061297757612977614e64565b60209081029190910101515160808501525b506129fb565b60008260038111156129a3576129a36140b8565b146129fb57825160600151604080516001600160401b03808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612ca5565b8251608001516001600160401b031615612ad1576000826003811115612a2357612a236140b8565b03612ad15782516080015160208401516040516370701e5760e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a81928f929190600401615af8565b6020604051808303816000875af1158015612aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac49190615627565b612ad15750505050612ca5565b60008c604001518681518110612ae957612ae9614e64565b6020026020010151905080518460a001515114612b3357835160600151604051631cfe6d8b60e01b81526001600160401b03808e1660048301529091166024820152604401610914565b612b478b85600001516060015160016135e4565b600080612b55868486613689565b91509150612b6c8d876000015160600151846135e4565b8b15612bc3576003826003811115612b8657612b866140b8565b03612bc3576000856003811115612b9f57612b9f6140b8565b14612bc357855151604051632b11b8d960e01b815261091491908390600401615b24565b6002826003811115612bd757612bd76140b8565b14612c18576003826003811115612bf057612bf06140b8565b14612c18578551606001516040516349362d1f60e11b8152610914918f918590600401615b3d565b8560000151600001518660000151606001516001600160401b03168e6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612c7057612c70614e64565b602002602001015186865a612c85908f614eca565b604051612c959493929190615b62565b60405180910390a4505050505050505b6001016127e4565b5050505050505050565b6040805180820190915260008082526020820152602086015160405163bbe4f6db60e01b81526001600160a01b0380831660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015612d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5f9190615b99565b90506001600160a01b0381161580612d8e5750612d8c6001600160a01b03821663aff2afbf60e01b611bdd565b155b15612db75760405163ae9b4ce960e01b81526001600160a01b0382166004820152602401610914565b600080612dcf88858c6040015163ffffffff1661373d565b915091506000806000612e826040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f608001518152602001896001600160a01b031681526020018f6000015181526020018f6060015181526020018b815250604051602401612e4c9190615bb6565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b17905287866113886084613822565b92509250925082612eaa578582604051634ff17cad60e11b8152600401610914929190615c82565b8151602014612ed9578151604051631e3be00960e21b8152602060048201526024810191909152604401610914565b600082806020019051810190612eef9190615ca4565b9050866001600160a01b03168c6001600160a01b031614612f6b576000612f208d8a612f1b868a614eca565b61373d565b50905086811080612f3a575081612f378883614eca565b14155b15612f695760405163a966e21f60e01b8152600481018390526024810188905260448101829052606401610914565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612fac826301ffc9a760e01b612fcc565b80156107dc5750612fc5826001600160e01b0319612fcc565b1592915050565b6040516001600160e01b031982166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d9150600051905082801561303f575060208210155b801561304b5750600081115b979650505050505050565b8251600090815b81811015612cad57600060018886846020811061307c5761307c614e64565b61308991901a601b6159d3565b89858151811061309b5761309b614e64565b60200260200101518986815181106130b5576130b5614e64565b6020026020010151604051600081526020016040526040516130f3949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015613115573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115613176576131766140b8565b6002811115613187576131876140b8565b90525090506001816020015160028111156131a4576131a46140b8565b146131c257604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b8516156131ec57604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b85179450505080600101905061305d565b60005b8151811015610a715760ff83166000908152600360205260408120835190919084908490811061323e5761323e614e64565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff1916905560010161320c565b60005b82518110156115a857600083828151811061329257613292614e64565b60200260200101519050600060028111156132af576132af6140b8565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156132ee576132ee6140b8565b1461330f576004604051631b3fab5160e11b81526004016109149190615a10565b6001600160a01b0381166133365760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561335c5761335c6140b8565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156133b9576133b96140b8565b021790555090505050806001019050613275565b60ff818116600081815260026020526040902060010154620100009004909116906134255780613410576040516317bd8dd160e11b815260040160405180910390fd5b600b805467ffffffffffffffff191690555050565b60001960ff8316016115ec5780156115ec576040516307b8c74d60e51b815260040160405180910390fd5b6000818152600183016020526040812054613497575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107dc565b5060006107dc565b81518051606080850151908301516080808701519401516040516000958695889561350395919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016135469190615d5e565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b6000806135b58585856138fc565b6001600160401b0387166000908152600a6020908152604080832093835292905220549150505b949350505050565b600060026135f3608085614ef3565b6001600160401b03166136069190614f19565b9050600061361485856118bc565b90508161362360016004614eca565b901b19168183600381111561363a5761363a6140b8565b6001600160401b03871660009081526009602052604081209190921b92909217918291613668608088615939565b6001600160401b031681526020810191909152604001600020555050505050565b604051630304c3e160e51b815260009060609030906360987c20906136b690889088908890600401615df5565b600060405180830381600087803b1580156136d057600080fd5b505af19250505080156136e1575060015b613720573d80801561370f576040519150601f19603f3d011682016040523d82523d6000602084013e613714565b606091505b50600392509050613735565b50506040805160208101909152600081526002905b935093915050565b600080600080600061379e8860405160240161376891906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b17905288886113886084613822565b925092509250826137c6578682604051634ff17cad60e11b8152600401610914929190615c82565b60208251146137f5578151604051631e3be00960e21b8152602060048201526024810191909152604401610914565b818060200190518101906138099190615ca4565b6138138288614eca565b94509450505050935093915050565b6000606060008361ffff166001600160401b0381111561384457613844613c3c565b6040519080825280601f01601f19166020018201604052801561386e576020820181803683370190505b509150863b6138885763030ed58f60e21b60005260046000fd5b5a858110156138a257632be8ca8b60e21b60005260046000fd5b85900360408104810387106138c2576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156138e55750835b808352806000602085013e50955095509592505050565b825182516000919081830361392457604051630469ac9960e21b815260040160405180910390fd5b610101821180159061393857506101018111155b613955576040516309bde33960e01b815260040160405180910390fd5b6000198282010161010081111561397f576040516309bde33960e01b815260040160405180910390fd5b806000036139ac578660008151811061399a5761399a614e64565b60200260200101519350505050613b7a565b6000816001600160401b038111156139c6576139c6613c3c565b6040519080825280602002602001820160405280156139ef578160200160208202803683370190505b50905060008080805b85811015613b195760006001821b8b811603613a535788851015613a3c578c5160018601958e918110613a2d57613a2d614e64565b60200260200101519050613a75565b8551600185019487918110613a2d57613a2d614e64565b8b5160018401938d918110613a6a57613a6a614e64565b602002602001015190505b600089861015613aa5578d5160018701968f918110613a9657613a96614e64565b60200260200101519050613ac7565b8651600186019588918110613abc57613abc614e64565b602002602001015190505b82851115613ae8576040516309bde33960e01b815260040160405180910390fd5b613af28282613b81565b878481518110613b0457613b04614e64565b602090810291909101015250506001016139f8565b506001850382148015613b2b57508683145b8015613b3657508581145b613b53576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613b6857613b68614e64565b60200260200101519750505050505050505b9392505050565b6000818310613b9957613b948284613b9f565b6107d9565b6107d983835b604080516001602082015290810183905260608101829052600090608001613589565b828054828255906000526020600020908101928215613c17579160200282015b82811115613c1757825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613be2565b50613c23929150613c27565b5090565b5b80821115613c235760008155600101613c28565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613c7457613c74613c3c565b60405290565b60405160a081016001600160401b0381118282101715613c7457613c74613c3c565b60405160c081016001600160401b0381118282101715613c7457613c74613c3c565b604080519081016001600160401b0381118282101715613c7457613c74613c3c565b604051606081016001600160401b0381118282101715613c7457613c74613c3c565b604051601f8201601f191681016001600160401b0381118282101715613d2a57613d2a613c3c565b604052919050565b60006001600160401b03821115613d4b57613d4b613c3c565b5060051b60200190565b6001600160a01b038116811461052f57600080fd5b80356001600160401b0381168114613d8157600080fd5b919050565b801515811461052f57600080fd5b8035613d8181613d86565b60006001600160401b03821115613db857613db8613c3c565b50601f01601f191660200190565b600082601f830112613dd757600080fd5b8135613dea613de582613d9f565b613d02565b818152846020838601011115613dff57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613e2f57600080fd5b82356001600160401b0380821115613e4657600080fd5b818501915085601f830112613e5a57600080fd5b8135613e68613de582613d32565b81815260059190911b83018401908481019088831115613e8757600080fd5b8585015b83811015613f2d57803585811115613ea35760008081fd5b86016080818c03601f1901811315613ebb5760008081fd5b613ec3613c52565b89830135613ed081613d55565b81526040613edf848201613d6a565b8b830152606080850135613ef281613d86565b83830152928401359289841115613f0b57600091508182fd5b613f198f8d86880101613dc6565b908301525085525050918601918601613e8b565b5098975050505050505050565b60005b83811015613f55578181015183820152602001613f3d565b50506000910152565b60008151808452613f76816020860160208601613f3a565b601f01601f19169290920160200192915050565b6020815260006107d96020830184613f5e565b6001600160a01b0381511682526020810151151560208301526001600160401b03604082015116604083015260006060820151608060608501526135dc6080850182613f5e565b604080825283519082018190526000906020906060840190828701845b828110156140265781516001600160401b031684529284019290840190600101614001565b50505083810382850152845180825282820190600581901b8301840187850160005b8381101561407657601f19868403018552614064838351613f9d565b94870194925090860190600101614048565b50909998505050505050505050565b6000806040838503121561409857600080fd5b6140a183613d6a565b91506140af60208401613d6a565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b600481106140de576140de6140b8565b9052565b602081016107dc82846140ce565b600060a0828403121561410257600080fd5b61410a613c7a565b90508135815261411c60208301613d6a565b602082015261412d60408301613d6a565b604082015261413e60608301613d6a565b606082015261414f60808301613d6a565b608082015292915050565b8035613d8181613d55565b803563ffffffff81168114613d8157600080fd5b600082601f83011261418a57600080fd5b8135602061419a613de583613d32565b82815260059290921b840181019181810190868411156141b957600080fd5b8286015b848110156142895780356001600160401b03808211156141dd5760008081fd5b9088019060a0828b03601f19018113156141f75760008081fd5b6141ff613c7a565b87840135838111156142115760008081fd5b61421f8d8a83880101613dc6565b82525060408085013561423181613d55565b828a01526060614242868201614165565b8284015260809150818601358581111561425c5760008081fd5b61426a8f8c838a0101613dc6565b91840191909152509190930135908301525083529183019183016141bd565b509695505050505050565b600061014082840312156142a757600080fd5b6142af613c9c565b90506142bb83836140f0565b815260a08201356001600160401b03808211156142d757600080fd5b6142e385838601613dc6565b602084015260c08401359150808211156142fc57600080fd5b61430885838601613dc6565b604084015261431960e0850161415a565b6060840152610100840135608084015261012084013591508082111561433e57600080fd5b5061434b84828501614179565b60a08301525092915050565b600082601f83011261436857600080fd5b81356020614378613de583613d32565b82815260059290921b8401810191818101908684111561439757600080fd5b8286015b848110156142895780356001600160401b038111156143ba5760008081fd5b6143c88986838b0101614294565b84525091830191830161439b565b600082601f8301126143e757600080fd5b813560206143f7613de583613d32565b82815260059290921b8401810191818101908684111561441657600080fd5b8286015b848110156142895780356001600160401b038082111561443957600080fd5b818901915089603f83011261444d57600080fd5b8582013561445d613de582613d32565b81815260059190911b830160400190878101908c83111561447d57600080fd5b604085015b838110156144b65780358581111561449957600080fd5b6144a88f6040838a0101613dc6565b845250918901918901614482565b5087525050509284019250830161441a565b600082601f8301126144d957600080fd5b813560206144e9613de583613d32565b8083825260208201915060208460051b87010193508684111561450b57600080fd5b602086015b848110156142895780358352918301918301614510565b600082601f83011261453857600080fd5b81356020614548613de583613d32565b82815260059290921b8401810191818101908684111561456757600080fd5b8286015b848110156142895780356001600160401b038082111561458b5760008081fd5b9088019060a0828b03601f19018113156145a55760008081fd5b6145ad613c7a565b6145b8888501613d6a565b8152604080850135848111156145ce5760008081fd5b6145dc8e8b83890101614357565b8a84015250606080860135858111156145f55760008081fd5b6146038f8c838a01016143d6565b838501525060809150818601358581111561461e5760008081fd5b61462c8f8c838a01016144c8565b918401919091525091909301359083015250835291830191830161456b565b6000806040838503121561465e57600080fd5b6001600160401b038335111561467357600080fd5b6146808484358501614527565b91506001600160401b036020840135111561469a57600080fd5b6020830135830184601f8201126146b057600080fd5b6146bd613de58235613d32565b81358082526020808301929160051b8401018710156146db57600080fd5b602083015b6020843560051b850101811015614881576001600160401b038135111561470657600080fd5b87603f82358601011261471857600080fd5b61472b613de56020833587010135613d32565b81358501602081810135808452908301929160059190911b016040018a101561475357600080fd5b604083358701015b83358701602081013560051b01604001811015614871576001600160401b038135111561478757600080fd5b833587018135016040818d03603f190112156147a257600080fd5b6147aa613cbe565b604082013581526001600160401b03606083013511156147c957600080fd5b8c605f6060840135840101126147de57600080fd5b60406060830135830101356147f5613de582613d32565b808282526020820191508f60608460051b606088013588010101111561481a57600080fd5b6060808601358601015b60608460051b6060880135880101018110156148515761484381614165565b835260209283019201614824565b50806020850152505050808552505060208301925060208101905061475b565b50845250602092830192016146e0565b508093505050509250929050565b60008083601f8401126148a157600080fd5b5081356001600160401b038111156148b857600080fd5b6020830191508360208260051b85010111156148d357600080fd5b9250929050565b6000806000806000606086880312156148f257600080fd5b85356001600160401b038082111561490957600080fd5b61491589838a01614294565b9650602088013591508082111561492b57600080fd5b61493789838a0161488f565b9096509450604088013591508082111561495057600080fd5b5061495d8882890161488f565b969995985093965092949392505050565b60006080828403121561498057600080fd5b614988613c52565b823561499381613d55565b81526149a160208401614165565b602082015260408301356149b481613d86565b604082015260608301356149c781613d55565b60608201529392505050565b6000602082840312156149e557600080fd5b81356001600160401b038111156149fb57600080fd5b820160a08185031215613b7a57600080fd5b803560ff81168114613d8157600080fd5b600060208284031215614a3057600080fd5b6107d982614a0d565b60008151808452602080850194506020840160005b83811015614a735781516001600160a01b031687529582019590820190600101614a4e565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614acd60e0840182614a39565b90506040840151601f198483030160c0850152614aea8282614a39565b95945050505050565b60008060408385031215614b0657600080fd5b614b0f83613d6a565b946020939093013593505050565b80604081018310156107dc57600080fd5b60008083601f840112614b4057600080fd5b5081356001600160401b03811115614b5757600080fd5b6020830191508360208285010111156148d357600080fd5b60008060008060008060008060c0898b031215614b8b57600080fd5b614b958a8a614b1d565b975060408901356001600160401b0380821115614bb157600080fd5b614bbd8c838d01614b2e565b909950975060608b0135915080821115614bd657600080fd5b614be28c838d0161488f565b909750955060808b0135915080821115614bfb57600080fd5b50614c088b828c0161488f565b999c989b50969995989497949560a00135949350505050565b600060208284031215614c3357600080fd5b6107d982613d6a565b6020815260006107d96020830184613f9d565b600060208284031215614c6157600080fd5b8135613b7a81613d55565b600080600060608486031215614c8157600080fd5b614c8b8585614b1d565b925060408401356001600160401b03811115614ca657600080fd5b614cb286828701614b2e565b9497909650939450505050565b600082601f830112614cd057600080fd5b81356020614ce0613de583613d32565b8083825260208201915060208460051b870101935086841115614d0257600080fd5b602086015b84811015614289578035614d1a81613d55565b8352918301918301614d07565b60006020808385031215614d3a57600080fd5b82356001600160401b0380821115614d5157600080fd5b818501915085601f830112614d6557600080fd5b8135614d73613de582613d32565b81815260059190911b83018401908481019088831115614d9257600080fd5b8585015b83811015613f2d57803585811115614dad57600080fd5b860160c0818c03601f19011215614dc45760008081fd5b614dcc613c9c565b8882013581526040614ddf818401614a0d565b8a8301526060614df0818501614a0d565b8284015260809150614e03828501613d94565b9083015260a08381013589811115614e1b5760008081fd5b614e298f8d83880101614cbf565b838501525060c0840135915088821115614e435760008081fd5b614e518e8c84870101614cbf565b9083015250845250918601918601614d96565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680614e8e57607f821691505b602082108103614eae57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156107dc576107dc614eb4565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b0380841680614f0d57614f0d614edd565b92169190910692915050565b80820281158282048414176107dc576107dc614eb4565b80518252600060206001600160401b0381840151168185015260408084015160a06040870152614f6360a0870182613f5e565b905060608501518682036060880152614f7c8282613f5e565b608087810151898303918a01919091528051808352908601935060009250908501905b80831015614fd157835180516001600160a01b0316835286015186830152928501926001929092019190840190614f9f565b50979650505050505050565b6020815260006107d96020830184614f30565b6080815260006150036080830187614f30565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561504157600080fd5b835161504c81613d86565b60208501519093506001600160401b0381111561506857600080fd5b8401601f8101861361507957600080fd5b8051615087613de582613d9f565b81815287602083850101111561509c57600080fd5b6150ad826020830160208601613f3a565b809450505050604084015190509250925092565b80356001600160e01b0381168114613d8157600080fd5b600082601f8301126150e957600080fd5b813560206150f9613de583613d32565b82815260069290921b8401810191818101908684111561511857600080fd5b8286015b8481101561428957604081890312156151355760008081fd5b61513d613cbe565b61514682613d6a565b81526151538583016150c1565b8186015283529183019160400161511c565b600082601f83011261517657600080fd5b81356020615186613de583613d32565b82815260059290921b840181019181810190868411156151a557600080fd5b8286015b848110156142895780356001600160401b03808211156151c95760008081fd5b9088019060a0828b03601f19018113156151e35760008081fd5b6151eb613c7a565b6151f6888501613d6a565b81526040808501358481111561520c5760008081fd5b61521a8e8b83890101613dc6565b8a840152506060935061522e848601613d6a565b90820152608061523f858201613d6a565b938201939093529201359082015283529183019183016151a9565b600082601f83011261526b57600080fd5b8135602061527b613de583613d32565b82815260069290921b8401810191818101908684111561529a57600080fd5b8286015b8481101561428957604081890312156152b75760008081fd5b6152bf613cbe565b81358152848201358582015283529183019160400161529e565b600060208083850312156152ec57600080fd5b82356001600160401b038082111561530357600080fd5b908401906060828703121561531757600080fd5b61531f613ce0565b82358281111561532e57600080fd5b8301604081890381131561534157600080fd5b615349613cbe565b82358581111561535857600080fd5b8301601f81018b1361536957600080fd5b8035615377613de582613d32565b81815260069190911b8201890190898101908d83111561539657600080fd5b928a01925b828410156153e65785848f0312156153b35760008081fd5b6153bb613cbe565b84356153c681613d55565b81526153d3858d016150c1565b818d0152825292850192908a019061539b565b8452505050828701359150848211156153fe57600080fd5b61540a8a8385016150d8565b8188015283525050828401358281111561542357600080fd5b61542f88828601615165565b8583015250604083013593508184111561544857600080fd5b6154548785850161525a565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b848110156154f457601f19868403018952815160a06001600160401b038083511686528683015182888801526154b883880182613f5e565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101615480565b5090979650505050505050565b6001600160a01b0384168152600060206060818401526155246060840186615463565b83810360408581019190915285518083528387019284019060005b818110156140765784518051845286015186840152938501939183019160010161553f565b805160408084528151848201819052600092602091908201906060870190855b818110156155bb57835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615584565b50508583015187820388850152805180835290840192506000918401905b80831015614fd157835180516001600160401b031683528501516001600160e01b0316858301529284019260019290920191908501906155d9565b6020815260006107d96020830184615564565b60006020828403121561563957600080fd5b8151613b7a81613d86565b600080835461565281614e7a565b6001828116801561566a576001811461567f576156ae565b60ff19841687528215158302870194506156ae565b8760005260208060002060005b858110156156a55781548a82015290840190820161568c565b50505082870194505b50929695505050505050565b600081546156c781614e7a565b8085526020600183811680156156e457600181146156fe5761572c565b60ff1985168884015283151560051b88018301955061572c565b866000528260002060005b858110156157245781548a8201860152908301908401615709565b890184019650505b505050505092915050565b60408152600061574a6040830185613f5e565b8281036020840152614aea81856156ba565b6001600160401b0381811683821601908082111561577c5761577c614eb4565b5092915050565b6040815260006157966040830185615463565b8281036020840152614aea8185615564565b6000602082840312156157ba57600080fd5b81356001600160401b038111156157d057600080fd5b6135dc84828501614527565b601f821115610a71576000816000526020600020601f850160051c810160208610156158055750805b601f850160051c820191505b8181101561582457828155600101615811565b505050505050565b81516001600160401b0381111561584557615845613c3c565b615859816158538454614e7a565b846157dc565b602080601f83116001811461588e57600084156158765750858301515b600019600386901b1c1916600185901b178555615824565b600085815260208120601f198616915b828110156158bd5788860151825594840194600190910190840161589e565b50858210156158db5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c166060840152506080808301526107d960a08301600185016156ba565b60006001600160401b038084168061595357615953614edd565b92169190910492915050565b60006020828403121561597157600080fd5b6107d982614165565b6000808335601e1984360301811261599157600080fd5b8301803591506001600160401b038211156159ab57600080fd5b6020019150368190038213156148d357600080fd5b808201808211156107dc576107dc614eb4565b60ff81811683821601908111156107dc576107dc614eb4565b8183823760009101908152919050565b828152604082602083013760600192915050565b6020810160068310615a2457615a246140b8565b91905290565b60ff818116838216029081169081811461577c5761577c614eb4565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615a9e5784546001600160a01b031683526001948501949284019201615a79565b50508481036060860152865180825290820192508187019060005b81811015615ade5782516001600160a01b031685529383019391830191600101615ab9565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b03808616835280851660208401525060606040830152614aea6060830184613f5e565b8281526040602082015260006135dc6040830184613f5e565b6001600160401b03848116825283166020820152606081016135dc60408301846140ce565b848152615b7260208201856140ce565b608060408201526000615b886080830185613f5e565b905082606083015295945050505050565b600060208284031215615bab57600080fd5b8151613b7a81613d55565b6020815260008251610100806020850152615bd5610120850183613f5e565b91506020850151615bf160408601826001600160401b03169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c2b60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c488483613f5e565b935060c08701519150808685030160e0870152615c658483613f5e565b935060e0870151915080868503018387015250615aee8382613f5e565b6001600160a01b03831681526040602082015260006135dc6040830184613f5e565b600060208284031215615cb657600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b848110156154f457601f19868403018952815160a08151818652615d0082870182613f5e565b9150506001600160a01b03868301511686860152604063ffffffff8184015116818701525060608083015186830382880152615d3c8382613f5e565b6080948501519790940196909652505098840198925090830190600101615cda565b6020815260006107d96020830184615cbd565b60008282518085526020808601955060208260051b8401016020860160005b848110156154f457601f19868403018952615dac838351613f5e565b98840198925090830190600101615d90565b60008151808452602080850194506020840160005b83811015614a7357815163ffffffff1687529582019590820190600101615dd3565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615e5d6101a0850183613f5e565b91506040870151605f198086850301610120870152615e7c8483613f5e565b935060608901519150615e99838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615ec28282615cbd565b9150508281036020840152615ed78186615d71565b90508281036040840152615aee8185615dbe56fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI @@ -560,27 +560,27 @@ func (_OffRamp *OffRampTransactorSession) ApplySourceChainConfigUpdates(sourceCh return _OffRamp.Contract.ApplySourceChainConfigUpdates(&_OffRamp.TransactOpts, sourceChainConfigUpdates) } -func (_OffRamp *OffRampTransactor) Commit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactor) Commit(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _OffRamp.contract.Transact(opts, "commit", reportContext, report, rs, ss, rawVs) } -func (_OffRamp *OffRampSession) Commit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_OffRamp *OffRampSession) Commit(reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _OffRamp.Contract.Commit(&_OffRamp.TransactOpts, reportContext, report, rs, ss, rawVs) } -func (_OffRamp *OffRampTransactorSession) Commit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactorSession) Commit(reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _OffRamp.Contract.Commit(&_OffRamp.TransactOpts, reportContext, report, rs, ss, rawVs) } -func (_OffRamp *OffRampTransactor) Execute(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactor) Execute(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte) (*types.Transaction, error) { return _OffRamp.contract.Transact(opts, "execute", reportContext, report) } -func (_OffRamp *OffRampSession) Execute(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { +func (_OffRamp *OffRampSession) Execute(reportContext [2][32]byte, report []byte) (*types.Transaction, error) { return _OffRamp.Contract.Execute(&_OffRamp.TransactOpts, reportContext, report) } -func (_OffRamp *OffRampTransactorSession) Execute(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactorSession) Execute(reportContext [2][32]byte, report []byte) (*types.Transaction, error) { return _OffRamp.Contract.Execute(&_OffRamp.TransactOpts, reportContext, report) } @@ -2505,9 +2505,9 @@ type OffRampInterface interface { ApplySourceChainConfigUpdates(opts *bind.TransactOpts, sourceChainConfigUpdates []OffRampSourceChainConfigArgs) (*types.Transaction, error) - Commit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) + Commit(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) - Execute(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) + Execute(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte) (*types.Transaction, error) ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go index dd7655b92a1..2c7c367ab1f 100644 --- a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go +++ b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go @@ -35,6 +35,11 @@ type IRMNRemoteSignature struct { S [32]byte } +type IRMNTaggedRoot struct { + CommitStore common.Address + Root [32]byte +} + type InternalMerkleRoot struct { SourceChainSelector uint64 OnRampAddress []byte @@ -55,15 +60,15 @@ type RMNRemoteSigner struct { } var RMNRemoteMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"AlreadyCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"NotCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Cursed\",\"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\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Uncursed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCursedSubjects\",\"outputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLocalChainSelector\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReportDigestHeader\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"digestHeader\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVersionedConfig\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"offrampAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b50604051620020ff380380620020ff833981016040819052620000349162000142565b336000816200005657604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b038481169190911790915581161562000089576200008981620000c8565b5050806001600160401b0316600003620000b65760405163273e150360e21b815260040160405180910390fd5b6001600160401b031660805262000174565b336001600160a01b03821603620000f257604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200015557600080fd5b81516001600160401b03811681146200016d57600080fd5b9392505050565b608051611f68620001976000396000818161027a0152610a2c0152611f686000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806370a9089e11610097578063d881e09211610066578063d881e09214610257578063eaa83ddd1461026c578063f2fde38b146102a4578063f8bb876e146102b757600080fd5b806370a9089e1461020157806379ba5097146102145780638da5cb5b1461021c5780639a19b3291461024457600080fd5b8063397796f7116100d3578063397796f7146101a557806362eed415146101ad5780636509a954146101c05780636d2d3993146101ee57600080fd5b8063181f5a7714610105578063198f0f77146101575780631add205f1461016c5780632cbc26bb14610182575b600080fd5b6101416040518060400160405280601381526020017f524d4e52656d6f746520312e362e302d6465760000000000000000000000000081525081565b60405161014e9190611389565b60405180910390f35b61016a61016536600461139c565b6102ca565b005b6101746106c4565b60405161014e9291906113d7565b6101956101903660046114b5565b6107bc565b604051901515815260200161014e565b610195610819565b61016a6101bb3660046114b5565b610893565b6040517f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf53815260200161014e565b61016a6101fc3660046114b5565b610907565b61016a61020f36600461153e565b610977565b61016a610cd2565b60015460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014e565b61016a6102523660046116bd565b610da0565b61025f610ea6565b60405161014e919061175a565b60405167ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161014e565b61016a6102b23660046117c0565b610eb2565b61016a6102c53660046116bd565b610ec6565b6102d2610fb8565b803561030a576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015b61031a60208301836117dd565b90508110156103ea5761033060208301836117dd565b8281811061034057610340611845565b90506040020160200160208101906103589190611895565b67ffffffffffffffff1661036f60208401846117dd565b61037a6001856118e1565b81811061038957610389611845565b90506040020160200160208101906103a19190611895565b67ffffffffffffffff16106103e2576040517f4485151700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60010161030d565b506103fb6060820160408301611895565b6104069060026118f4565b610411906001611920565b67ffffffffffffffff1661042860208301836117dd565b90501015610462576040517f014c502000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003545b80156104f45760086000600361047d6001856118e1565b8154811061048d5761048d611845565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556104ed81611941565b9050610466565b5060005b61050560208301836117dd565b905081101561063a576008600061051f60208501856117dd565b8481811061052f5761052f611845565b61054592602060409092020190810191506117c0565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff16156105a6576040517f28cae27d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600860006105b960208601866117dd565b858181106105c9576105c9611845565b6105df92602060409092020190810191506117c0565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556001016104f8565b508060026106488282611a2f565b5050600580546000919082906106639063ffffffff16611b6a565b91906101000a81548163ffffffff021916908363ffffffff160217905590508063ffffffff167f7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c836040516106b89190611b8d565b60405180910390a25050565b6040805160608082018352600080835260208301919091529181018290526005546040805160608101825260028054825260038054845160208281028201810190965281815263ffffffff9096169592948593818601939092909160009084015b82821015610793576000848152602090819020604080518082019091529084015473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000900467ffffffffffffffff1681830152825260019092019101610725565b505050908252506002919091015467ffffffffffffffff16602090910152919491935090915050565b60006107c8600661100b565b6000036107d757506000919050565b6107e2600683611015565b80610813575061081360067f0100000000000000000000000000000100000000000000000000000000000000611015565b92915050565b6000610825600661100b565b6000036108325750600090565b61085d60067f0100000000000000000000000000000000000000000000000000000000000000611015565b8061088e575061088e60067f0100000000000000000000000000000100000000000000000000000000000000611015565b905090565b6040805160018082528183019092526000916020808301908036833701905050905081816000815181106108c9576108c9611845565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000009092166020928302919091019091015261090381610ec6565b5050565b60408051600180825281830190925260009160208083019080368337019050509050818160008151811061093d5761093d611845565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000009092166020928302919091019091015261090381610da0565b60055463ffffffff166000036109b9576040517face124bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004546109d19067ffffffffffffffff166001611920565b67ffffffffffffffff16811015610a14576040517f59fa4a9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160c08101825246815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166020820152309181019190915273ffffffffffffffffffffffffffffffffffffffff8616606082015260025460808201526000907f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf539060a08101610ab08789611c97565b9052604051610ac3929190602001611df7565b60405160208183030381529060405280519060200120905060008060005b84811015610cc757600184601b888885818110610b0057610b00611845565b90506040020160000135898986818110610b1c57610b1c611845565b9050604002016020013560405160008152602001604052604051610b5c949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610b7e573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015192505073ffffffffffffffffffffffffffffffffffffffff8216610bf6576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1610610c5b576040517fbbe15e7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526008602052604090205460ff16610cba576040517faaaa914100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9091508190600101610ae1565b505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d23576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610da8610fb8565b60005b8151811015610e6b57610de1828281518110610dc957610dc9611845565b6020026020010151600661105390919063ffffffff16565b610e6357818181518110610df757610df7611845565b60200260200101516040517f73281fa1000000000000000000000000000000000000000000000000000000008152600401610e5a91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b60405180910390fd5b600101610dab565b507f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba181604051610e9b919061175a565b60405180910390a150565b606061088e6006611081565b610eba610fb8565b610ec38161108e565b50565b610ece610fb8565b60005b8151811015610f8857610f07828281518110610eef57610eef611845565b6020026020010151600661115290919063ffffffff16565b610f8057818181518110610f1d57610f1d611845565b60200260200101516040517f19d5c79b000000000000000000000000000000000000000000000000000000008152600401610e5a91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b600101610ed1565b507f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7481604051610e9b919061175a565b60015473ffffffffffffffffffffffffffffffffffffffff163314611009576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000610813825490565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008116600090815260018301602052604081205415155b9392505050565b600061104c837fffffffffffffffffffffffffffffffff000000000000000000000000000000008416611180565b6060600061104c8361127a565b3373ffffffffffffffffffffffffffffffffffffffff8216036110dd576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600061104c837fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166112d6565b600081815260018301602052604081205480156112695760006111a46001836118e1565b85549091506000906111b8906001906118e1565b905080821461121d5760008660000182815481106111d8576111d8611845565b90600052602060002001549050808760000184815481106111fb576111fb611845565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061122e5761122e611f2c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610813565b6000915050610813565b5092915050565b6060816000018054806020026020016040519081016040528092919081815260200182805480156112ca57602002820191906000526020600020905b8154815260200190600101908083116112b6575b50505050509050919050565b600081815260018301602052604081205461131d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610813565b506000610813565b6000815180845260005b8181101561134b5760208185018101518683018201520161132f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061104c6020830184611325565b6000602082840312156113ae57600080fd5b813567ffffffffffffffff8111156113c557600080fd5b82016060818503121561104c57600080fd5b63ffffffff831681526040602080830182905283518383015283810151606080850152805160a085018190526000939291820190849060c08701905b8083101561145c578351805173ffffffffffffffffffffffffffffffffffffffff16835285015167ffffffffffffffff1685830152928401926001929092019190850190611413565b50604088015167ffffffffffffffff81166080890152945098975050505050505050565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146114b057600080fd5b919050565b6000602082840312156114c757600080fd5b61104c82611480565b73ffffffffffffffffffffffffffffffffffffffff81168114610ec357600080fd5b60008083601f84011261150457600080fd5b50813567ffffffffffffffff81111561151c57600080fd5b6020830191508360208260061b850101111561153757600080fd5b9250929050565b60008060008060006060868803121561155657600080fd5b8535611561816114d0565b9450602086013567ffffffffffffffff8082111561157e57600080fd5b818801915088601f83011261159257600080fd5b8135818111156115a157600080fd5b8960208260051b85010111156115b657600080fd5b6020830196508095505060408801359150808211156115d457600080fd5b506115e1888289016114f2565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715611644576116446115f2565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611691576116916115f2565b604052919050565b600067ffffffffffffffff8211156116b3576116b36115f2565b5060051b60200190565b600060208083850312156116d057600080fd5b823567ffffffffffffffff8111156116e757600080fd5b8301601f810185136116f857600080fd5b803561170b61170682611699565b61164a565b81815260059190911b8201830190838101908783111561172a57600080fd5b928401925b8284101561174f5761174084611480565b8252928401929084019061172f565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156117b45783517fffffffffffffffffffffffffffffffff000000000000000000000000000000001683529284019291840191600101611776565b50909695505050505050565b6000602082840312156117d257600080fd5b813561104c816114d0565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261181257600080fd5b83018035915067ffffffffffffffff82111561182d57600080fd5b6020019150600681901b360382131561153757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff81168114610ec357600080fd5b80356114b081611874565b6000602082840312156118a757600080fd5b813561104c81611874565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610813576108136118b2565b67ffffffffffffffff818116838216028082169190828114611918576119186118b2565b505092915050565b67ffffffffffffffff818116838216019080821115611273576112736118b2565b600081611950576119506118b2565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b6000813561081381611874565b813561198e816114d0565b73ffffffffffffffffffffffffffffffffffffffff811690508154817fffffffffffffffffffffffff0000000000000000000000000000000000000000821617835560208401356119de81611874565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b16837fffffffff000000000000000000000000000000000000000000000000000000008416171784555050505050565b81358155600180820160208401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112611a6d57600080fd5b8401803567ffffffffffffffff811115611a8657600080fd5b6020820191508060061b3603821315611a9e57600080fd5b68010000000000000000811115611ab757611ab76115f2565b825481845580821015611aec576000848152602081208381019083015b80821015611ae85782825590870190611ad4565b5050505b50600092835260208320925b81811015611b1c57611b0a8385611983565b92840192604092909201918401611af8565b5050505050610903611b3060408401611976565b6002830167ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161781555050565b600063ffffffff808316818103611b8357611b836118b2565b6001019392505050565b6000602080835260808301843582850152818501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1863603018112611bd257600080fd5b8501828101903567ffffffffffffffff80821115611bef57600080fd5b8160061b3603831315611c0157600080fd5b6040606060408901528483865260a089019050849550600094505b83851015611c6c578535611c2f816114d0565b73ffffffffffffffffffffffffffffffffffffffff16815285870135611c5481611874565b83168188015294810194600194909401938101611c1c565b611c7860408b0161188a565b67ffffffffffffffff811660608b015296509998505050505050505050565b6000611ca561170684611699565b80848252602080830192508560051b850136811115611cc357600080fd5b855b81811015611deb57803567ffffffffffffffff80821115611ce65760008081fd5b818901915060a08236031215611cfc5760008081fd5b611d04611621565b8235611d0f81611874565b81528286013582811115611d235760008081fd5b8301601f3681830112611d365760008081fd5b813584811115611d4857611d486115f2565b611d77897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848401160161164a565b94508085523689828501011115611d9057600091508182fd5b808984018a8701376000898287010152505050818682015260409150611db782840161188a565b8282015260609150611dca82840161188a565b91810191909152608091820135918101919091528552938201938201611cc5565b50919695505050505050565b60006040848352602060408185015261010084018551604086015281860151606067ffffffffffffffff808316606089015260408901519250608073ffffffffffffffffffffffffffffffffffffffff80851660808b015260608b0151945060a081861660a08c015260808c015160c08c015260a08c0151955060c060e08c015286915085518088526101209750878c019250878160051b8d01019750888701965060005b81811015611f19577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee08d8a030184528751868151168a528a810151848c8c0152611ee8858c0182611325565b828e015189168c8f01528983015189168a8d0152918701519a87019a909a5298509689019692890192600101611e9c565b50969d9c50505050505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMN\",\"name\":\"legacyRMN\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"AlreadyCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IsBlessedNotAvailable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"NotCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Cursed\",\"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\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Uncursed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCursedSubjects\",\"outputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLocalChainSelector\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReportDigestHeader\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"digestHeader\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVersionedConfig\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMN.TaggedRoot\",\"name\":\"taggedRoot\",\"type\":\"tuple\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"offrampAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60c06040523480156200001157600080fd5b506040516200230438038062002304833981016040819052620000349162000150565b336000816200005657604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b038481169190911790915581161562000089576200008981620000d6565b5050816001600160401b0316600003620000b65760405163273e150360e21b815260040160405180910390fd5b6001600160401b039091166080526001600160a01b031660a052620001a5565b336001600160a01b038216036200010057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080604083850312156200016457600080fd5b82516001600160401b03811681146200017c57600080fd5b60208401519092506001600160a01b03811681146200019a57600080fd5b809150509250929050565b60805160a05161212b620001d9600039600081816108c5015261096d0152600081816102a80152610b7c015261212b6000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c80636d2d3993116100b25780639a19b32911610081578063eaa83ddd11610066578063eaa83ddd1461029a578063f2fde38b146102d2578063f8bb876e146102e557600080fd5b80639a19b32914610272578063d881e0921461028557600080fd5b80636d2d39931461021c57806370a9089e1461022f57806379ba5097146102425780638da5cb5b1461024a57600080fd5b8063397796f7116100ee578063397796f7146101c05780634d616771146101c857806362eed415146101db5780636509a954146101ee57600080fd5b8063181f5a7714610120578063198f0f77146101725780631add205f146101875780632cbc26bb1461019d575b600080fd5b61015c6040518060400160405280601381526020017f524d4e52656d6f746520312e362e302d6465760000000000000000000000000081525081565b60405161016991906114d9565b60405180910390f35b6101856101803660046114ec565b6102f8565b005b61018f6106f2565b604051610169929190611527565b6101b06101ab366004611605565b6107ea565b6040519015158152602001610169565b6101b0610847565b6101b06101d6366004611620565b6108c1565b6101856101e9366004611605565b6109e3565b6040517f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf538152602001610169565b61018561022a366004611605565b610a57565b61018561023d3660046116a6565b610ac7565b610185610e22565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610169565b610185610280366004611825565b610ef0565b61028d610ff6565b60405161016991906118c2565b60405167ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610169565b6101856102e0366004611928565b611002565b6101856102f3366004611825565b611016565b610300611108565b8035610338576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015b6103486020830183611945565b90508110156104185761035e6020830183611945565b8281811061036e5761036e6119ad565b905060400201602001602081019061038691906119fd565b67ffffffffffffffff1661039d6020840184611945565b6103a8600185611a49565b8181106103b7576103b76119ad565b90506040020160200160208101906103cf91906119fd565b67ffffffffffffffff1610610410576040517f4485151700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60010161033b565b5061042960608201604083016119fd565b610434906002611a5c565b61043f906001611a88565b67ffffffffffffffff166104566020830183611945565b90501015610490576040517f014c502000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003545b8015610522576008600060036104ab600185611a49565b815481106104bb576104bb6119ad565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905561051b81611aa9565b9050610494565b5060005b6105336020830183611945565b9050811015610668576008600061054d6020850185611945565b8481811061055d5761055d6119ad565b6105739260206040909202019081019150611928565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff16156105d4576040517f28cae27d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600860006105e76020860186611945565b858181106105f7576105f76119ad565b61060d9260206040909202019081019150611928565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101610526565b508060026106768282611b97565b5050600580546000919082906106919063ffffffff16611cd2565b91906101000a81548163ffffffff021916908363ffffffff160217905590508063ffffffff167f7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c836040516106e69190611cf5565b60405180910390a25050565b6040805160608082018352600080835260208301919091529181018290526005546040805160608101825260028054825260038054845160208281028201810190965281815263ffffffff9096169592948593818601939092909160009084015b828210156107c1576000848152602090819020604080518082019091529084015473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000900467ffffffffffffffff1681830152825260019092019101610753565b505050908252506002919091015467ffffffffffffffff16602090910152919491935090915050565b60006107f6600661115b565b60000361080557506000919050565b610810600683611165565b80610841575061084160067f0100000000000000000000000000000100000000000000000000000000000000611165565b92915050565b6000610853600661115b565b6000036108605750600090565b61088b60067f0100000000000000000000000000000000000000000000000000000000000000611165565b806108bc57506108bc60067f0100000000000000000000000000000100000000000000000000000000000000611165565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610930576040517f0a7c4edd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f4d61677100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690634d616771906109a2908590600401611dff565b602060405180830381865afa1580156109bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108419190611e38565b604080516001808252818301909252600091602080830190803683370190505090508181600081518110610a1957610a196119ad565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921660209283029190910190910152610a5381611016565b5050565b604080516001808252818301909252600091602080830190803683370190505090508181600081518110610a8d57610a8d6119ad565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921660209283029190910190910152610a5381610ef0565b60055463ffffffff16600003610b09576040517face124bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454610b219067ffffffffffffffff166001611a88565b67ffffffffffffffff16811015610b64576040517f59fa4a9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160c08101825246815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166020820152309181019190915273ffffffffffffffffffffffffffffffffffffffff8616606082015260025460808201526000907f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf539060a08101610c008789611e5a565b9052604051610c13929190602001611fba565b60405160208183030381529060405280519060200120905060008060005b84811015610e1757600184601b888885818110610c5057610c506119ad565b90506040020160000135898986818110610c6c57610c6c6119ad565b9050604002016020013560405160008152602001604052604051610cac949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610cce573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015192505073ffffffffffffffffffffffffffffffffffffffff8216610d46576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1610610dab576040517fbbe15e7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526008602052604090205460ff16610e0a576040517faaaa914100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9091508190600101610c31565b505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e73576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ef8611108565b60005b8151811015610fbb57610f31828281518110610f1957610f196119ad565b602002602001015160066111a390919063ffffffff16565b610fb357818181518110610f4757610f476119ad565b60200260200101516040517f73281fa1000000000000000000000000000000000000000000000000000000008152600401610faa91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b60405180910390fd5b600101610efb565b507f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba181604051610feb91906118c2565b60405180910390a150565b60606108bc60066111d1565b61100a611108565b611013816111de565b50565b61101e611108565b60005b81518110156110d85761105782828151811061103f5761103f6119ad565b602002602001015160066112a290919063ffffffff16565b6110d05781818151811061106d5761106d6119ad565b60200260200101516040517f19d5c79b000000000000000000000000000000000000000000000000000000008152600401610faa91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b600101611021565b507f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7481604051610feb91906118c2565b60015473ffffffffffffffffffffffffffffffffffffffff163314611159576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000610841825490565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008116600090815260018301602052604081205415155b9392505050565b600061119c837fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166112d0565b6060600061119c836113ca565b3373ffffffffffffffffffffffffffffffffffffffff82160361122d576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600061119c837fffffffffffffffffffffffffffffffff000000000000000000000000000000008416611426565b600081815260018301602052604081205480156113b95760006112f4600183611a49565b855490915060009061130890600190611a49565b905080821461136d576000866000018281548110611328576113286119ad565b906000526020600020015490508087600001848154811061134b5761134b6119ad565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061137e5761137e6120ef565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610841565b6000915050610841565b5092915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561141a57602002820191906000526020600020905b815481526020019060010190808311611406575b50505050509050919050565b600081815260018301602052604081205461146d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610841565b506000610841565b6000815180845260005b8181101561149b5760208185018101518683018201520161147f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061119c6020830184611475565b6000602082840312156114fe57600080fd5b813567ffffffffffffffff81111561151557600080fd5b82016060818503121561119c57600080fd5b63ffffffff831681526040602080830182905283518383015283810151606080850152805160a085018190526000939291820190849060c08701905b808310156115ac578351805173ffffffffffffffffffffffffffffffffffffffff16835285015167ffffffffffffffff1685830152928401926001929092019190850190611563565b50604088015167ffffffffffffffff81166080890152945098975050505050505050565b80357fffffffffffffffffffffffffffffffff000000000000000000000000000000008116811461160057600080fd5b919050565b60006020828403121561161757600080fd5b61119c826115d0565b60006040828403121561163257600080fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461101357600080fd5b60008083601f84011261166c57600080fd5b50813567ffffffffffffffff81111561168457600080fd5b6020830191508360208260061b850101111561169f57600080fd5b9250929050565b6000806000806000606086880312156116be57600080fd5b85356116c981611638565b9450602086013567ffffffffffffffff808211156116e657600080fd5b818801915088601f8301126116fa57600080fd5b81358181111561170957600080fd5b8960208260051b850101111561171e57600080fd5b60208301965080955050604088013591508082111561173c57600080fd5b506117498882890161165a565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156117ac576117ac61175a565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156117f9576117f961175a565b604052919050565b600067ffffffffffffffff82111561181b5761181b61175a565b5060051b60200190565b6000602080838503121561183857600080fd5b823567ffffffffffffffff81111561184f57600080fd5b8301601f8101851361186057600080fd5b803561187361186e82611801565b6117b2565b81815260059190911b8201830190838101908783111561189257600080fd5b928401925b828410156118b7576118a8846115d0565b82529284019290840190611897565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561191c5783517fffffffffffffffffffffffffffffffff0000000000000000000000000000000016835292840192918401916001016118de565b50909695505050505050565b60006020828403121561193a57600080fd5b813561119c81611638565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261197a57600080fd5b83018035915067ffffffffffffffff82111561199557600080fd5b6020019150600681901b360382131561169f57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff8116811461101357600080fd5b8035611600816119dc565b600060208284031215611a0f57600080fd5b813561119c816119dc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561084157610841611a1a565b67ffffffffffffffff818116838216028082169190828114611a8057611a80611a1a565b505092915050565b67ffffffffffffffff8181168382160190808211156113c3576113c3611a1a565b600081611ab857611ab8611a1a565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60008135610841816119dc565b8135611af681611638565b73ffffffffffffffffffffffffffffffffffffffff811690508154817fffffffffffffffffffffffff000000000000000000000000000000000000000082161783556020840135611b46816119dc565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b16837fffffffff000000000000000000000000000000000000000000000000000000008416171784555050505050565b81358155600180820160208401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112611bd557600080fd5b8401803567ffffffffffffffff811115611bee57600080fd5b6020820191508060061b3603821315611c0657600080fd5b68010000000000000000811115611c1f57611c1f61175a565b825481845580821015611c54576000848152602081208381019083015b80821015611c505782825590870190611c3c565b5050505b50600092835260208320925b81811015611c8457611c728385611aeb565b92840192604092909201918401611c60565b5050505050610a53611c9860408401611ade565b6002830167ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161781555050565b600063ffffffff808316818103611ceb57611ceb611a1a565b6001019392505050565b6000602080835260808301843582850152818501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1863603018112611d3a57600080fd5b8501828101903567ffffffffffffffff80821115611d5757600080fd5b8160061b3603831315611d6957600080fd5b6040606060408901528483865260a089019050849550600094505b83851015611dd4578535611d9781611638565b73ffffffffffffffffffffffffffffffffffffffff16815285870135611dbc816119dc565b83168188015294810194600194909401938101611d84565b611de060408b016119f2565b67ffffffffffffffff811660608b015296509998505050505050505050565b604081018235611e0e81611638565b73ffffffffffffffffffffffffffffffffffffffff81168352506020830135602083015292915050565b600060208284031215611e4a57600080fd5b8151801515811461119c57600080fd5b6000611e6861186e84611801565b80848252602080830192508560051b850136811115611e8657600080fd5b855b81811015611fae57803567ffffffffffffffff80821115611ea95760008081fd5b818901915060a08236031215611ebf5760008081fd5b611ec7611789565b8235611ed2816119dc565b81528286013582811115611ee65760008081fd5b8301601f3681830112611ef95760008081fd5b813584811115611f0b57611f0b61175a565b611f3a897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084840116016117b2565b94508085523689828501011115611f5357600091508182fd5b808984018a8701376000898287010152505050818682015260409150611f7a8284016119f2565b8282015260609150611f8d8284016119f2565b91810191909152608091820135918101919091528552938201938201611e88565b50919695505050505050565b60006040848352602060408185015261010084018551604086015281860151606067ffffffffffffffff808316606089015260408901519250608073ffffffffffffffffffffffffffffffffffffffff80851660808b015260608b0151945060a081861660a08c015260808c015160c08c015260a08c0151955060c060e08c015286915085518088526101209750878c019250878160051b8d01019750888701965060005b818110156120dc577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee08d8a030184528751868151168a528a810151848c8c01526120ab858c0182611475565b828e015189168c8f01528983015189168a8d0152918701519a87019a909a529850968901969289019260010161205f565b50969d9c50505050505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var RMNRemoteABI = RMNRemoteMetaData.ABI var RMNRemoteBin = RMNRemoteMetaData.Bin -func DeployRMNRemote(auth *bind.TransactOpts, backend bind.ContractBackend, localChainSelector uint64) (common.Address, *types.Transaction, *RMNRemote, error) { +func DeployRMNRemote(auth *bind.TransactOpts, backend bind.ContractBackend, localChainSelector uint64, legacyRMN common.Address) (common.Address, *types.Transaction, *RMNRemote, error) { parsed, err := RMNRemoteMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -72,7 +77,7 @@ func DeployRMNRemote(auth *bind.TransactOpts, backend bind.ContractBackend, loca return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(RMNRemoteBin), backend, localChainSelector) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(RMNRemoteBin), backend, localChainSelector, legacyRMN) if err != nil { return common.Address{}, nil, nil, err } @@ -291,6 +296,28 @@ func (_RMNRemote *RMNRemoteCallerSession) GetVersionedConfig() (GetVersionedConf return _RMNRemote.Contract.GetVersionedConfig(&_RMNRemote.CallOpts) } +func (_RMNRemote *RMNRemoteCaller) IsBlessed(opts *bind.CallOpts, taggedRoot IRMNTaggedRoot) (bool, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "isBlessed", taggedRoot) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) IsBlessed(taggedRoot IRMNTaggedRoot) (bool, error) { + return _RMNRemote.Contract.IsBlessed(&_RMNRemote.CallOpts, taggedRoot) +} + +func (_RMNRemote *RMNRemoteCallerSession) IsBlessed(taggedRoot IRMNTaggedRoot) (bool, error) { + return _RMNRemote.Contract.IsBlessed(&_RMNRemote.CallOpts, taggedRoot) +} + func (_RMNRemote *RMNRemoteCaller) IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) { var out []interface{} err := _RMNRemote.contract.Call(opts, &out, "isCursed", subject) @@ -1175,6 +1202,8 @@ type RMNRemoteInterface interface { error) + IsBlessed(opts *bind.CallOpts, taggedRoot IRMNTaggedRoot) (bool, error) + IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) IsCursed0(opts *bind.CallOpts) (bool, error) diff --git a/core/gethwrappers/ccip/generated/token_pool/token_pool.go b/core/gethwrappers/ccip/generated/token_pool/token_pool.go index af6333e22d3..5032b336e0a 100644 --- a/core/gethwrappers/ccip/generated/token_pool/token_pool.go +++ b/core/gethwrappers/ccip/generated/token_pool/token_pool.go @@ -81,7 +81,7 @@ type TokenPoolChainUpdate struct { } var TokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"lockOrBurnOut\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"lockOrBurnOut\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } var TokenPoolABI = TokenPoolMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go b/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go index 0462cd036ba..ca6c4a1977f 100644 --- a/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go +++ b/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go @@ -94,8 +94,8 @@ type USDCTokenPoolDomainUpdate struct { } var USDCTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"tokenMessenger\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidDestinationDomain\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate\",\"name\":\"domain\",\"type\":\"tuple\"}],\"name\":\"InvalidDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidMessageVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"}],\"name\":\"InvalidNonce\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"}],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidSourceDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidTokenMessengerVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"domain\",\"type\":\"uint64\"}],\"name\":\"UnknownDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnlockingUSDCFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenMessenger\",\"type\":\"address\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"name\":\"DomainsSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SUPPORTED_USDC_VERSION\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getDomain\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.Domain\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_localDomainIdentifier\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_messageTransmitter\",\"outputs\":[{\"internalType\":\"contractIMessageTransmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_tokenMessenger\",\"outputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"domains\",\"type\":\"tuple[]\"}],\"name\":\"setDomains\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101606040523480156200001257600080fd5b50604051620053f5380380620053f5833981016040819052620000359162000af6565b836006848484336000816200005d57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b038481169190911790915581161562000090576200009081620003f6565b50506001600160a01b0385161580620000b057506001600160a01b038116155b80620000c357506001600160a01b038216155b15620000e2576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0385811660805282811660c05260ff851660a052600480546001600160a01b031916918316919091179055825115801560e0526200013c576040805160008152602081019091526200013c908462000470565b5050506001600160a01b03871691506200016b9050576040516306b7c75960e31b815260040160405180910390fd5b6000856001600160a01b0316632c1219216040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001ac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001d2919062000c1c565b90506000816001600160a01b03166354fd4d506040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000215573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200023b919062000c43565b905063ffffffff81161562000270576040516334697c6b60e11b815263ffffffff821660048201526024015b60405180910390fd5b6000876001600160a01b0316639cdbb1816040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002d7919062000c43565b905063ffffffff81161562000308576040516316ba39c560e31b815263ffffffff8216600482015260240162000267565b6001600160a01b038089166101005283166101208190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa1580156200035b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000381919062000c43565b63ffffffff166101405261010051608051620003ac916001600160a01b0390911690600019620005cd565b6040516001600160a01b03891681527f2e902d38f15b233cbb63711add0fca4545334d3a169d60c0a616494d7eea95449060200160405180910390a1505050505050505062000d90565b336001600160a01b038216036200042057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e05162000491576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200051c576000838281518110620004b557620004b562000c6b565b60209081029190910101519050620004cf600282620006b3565b1562000512576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000494565b5060005b8151811015620005c857600082828151811062000541576200054162000c6b565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200056d5750620005bf565b6200057a600282620006d3565b15620005bd576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000520565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000645919062000c81565b62000651919062000cb1565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620006ad91869190620006ea16565b50505050565b6000620006ca836001600160a01b038416620007bb565b90505b92915050565b6000620006ca836001600160a01b038416620008bf565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000739906001600160a01b03851690849062000911565b805190915015620005c857808060200190518101906200075a919062000cc7565b620005c85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000267565b60008181526001830160205260408120548015620008b4576000620007e260018362000ceb565b8554909150600090620007f89060019062000ceb565b9050808214620008645760008660000182815481106200081c576200081c62000c6b565b906000526020600020015490508087600001848154811062000842576200084262000c6b565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000878576200087862000d01565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620006cd565b6000915050620006cd565b60008181526001830160205260408120546200090857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620006cd565b506000620006cd565b60606200092284846000856200092a565b949350505050565b6060824710156200098d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000267565b600080866001600160a01b03168587604051620009ab919062000d3d565b60006040518083038185875af1925050503d8060008114620009ea576040519150601f19603f3d011682016040523d82523d6000602084013e620009ef565b606091505b50909250905062000a038783838762000a0e565b979650505050505050565b6060831562000a8257825160000362000a7a576001600160a01b0385163b62000a7a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000267565b508162000922565b62000922838381511562000a995781518083602001fd5b8060405162461bcd60e51b815260040162000267919062000d5b565b6001600160a01b038116811462000acb57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000af18162000ab5565b919050565b600080600080600060a0868803121562000b0f57600080fd5b855162000b1c8162000ab5565b8095505060208087015162000b318162000ab5565b60408801519095506001600160401b038082111562000b4f57600080fd5b818901915089601f83011262000b6457600080fd5b81518181111562000b795762000b7962000ace565b8060051b604051601f19603f8301168101818110858211171562000ba15762000ba162000ace565b60405291825284820192508381018501918c83111562000bc057600080fd5b938501935b8285101562000be95762000bd98562000ae4565b8452938501939285019262000bc5565b80985050505050505062000c006060870162000ae4565b915062000c106080870162000ae4565b90509295509295909350565b60006020828403121562000c2f57600080fd5b815162000c3c8162000ab5565b9392505050565b60006020828403121562000c5657600080fd5b815163ffffffff8116811462000c3c57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000c9457600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620006cd57620006cd62000c9b565b60006020828403121562000cda57600080fd5b8151801515811462000c3c57600080fd5b81810381811115620006cd57620006cd62000c9b565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000d3457818101518382015260200162000d1a565b50506000910152565b6000825162000d5181846020870162000d17565b9190910192915050565b602081526000825180602084015262000d7c81604085016020870162000d17565b601f01601f19169190910160400192915050565b60805160a05160c05160e0516101005161012051610140516145af62000e46600039600081816104170152818161113c01528181612107015261216501526000818161072b0152610a750152600081816103dd01526110520152600081816106dc0152818161221d0152612bcc01526000818161061801528181611eb40152612509015260006103660152600081816102cd015281816103220152818161101c01528181612b620152612db701526145af6000f3fe608060405234801561001057600080fd5b50600436106102405760003560e01c80639a4575b911610145578063c4bffe2b116100bd578063dfadfa351161008c578063e8a1da1711610071578063e8a1da1714610700578063f2fde38b14610713578063fbf84dd71461072657600080fd5b8063dfadfa351461063c578063e0351e13146106da57600080fd5b8063c4bffe2b146105db578063c75eea9c146105f0578063cf7401f314610603578063dc0bd9711461061657600080fd5b8063acfecf9111610114578063b0f479a1116100f9578063b0f479a114610597578063b7946580146105b5578063c0d78655146105c857600080fd5b8063acfecf9114610515578063af58d59f1461052857600080fd5b80639a4575b9146104b85780639fdf13ff146104d8578063a42a7b8b146104e0578063a7cd63b71461050057600080fd5b806354c8a4f3116101d85780636d3d1a58116101a75780637d54534e1161018c5780637d54534e146104745780638926f54f146104875780638da5cb5b1461049a57600080fd5b80636d3d1a581461044e57806379ba50971461046c57600080fd5b806354c8a4f3146103c55780636155cda0146103d857806362ddd3c4146103ff5780636b716b0d1461041257600080fd5b8063240028e811610214578063240028e81461031257806324f65ee71461035f57806339077537146103905780634c5ef0ed146103b257600080fd5b806241d3c11461024557806301ffc9a71461025a578063181f5a771461028257806321df0da7146102cb575b600080fd5b610258610253366004613577565b61074d565b005b61026d6102683660046135ec565b6108ea565b60405190151581526020015b60405180910390f35b6102be6040518060400160405280601381526020017f55534443546f6b656e506f6f6c20312e352e310000000000000000000000000081525081565b6040516102799190613692565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610279565b61026d6103203660046136c7565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610279565b6103a361039e3660046136e4565b6109cf565b60405190518152602001610279565b61026d6103c0366004613736565b610bb4565b6102586103d3366004613807565b610bfe565b6102ed7f000000000000000000000000000000000000000000000000000000000000000081565b61025861040d366004613736565b610c79565b6104397f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610279565b60095473ffffffffffffffffffffffffffffffffffffffff166102ed565b610258610d11565b6102586104823660046136c7565b610ddf565b61026d610495366004613873565b610e60565b60015473ffffffffffffffffffffffffffffffffffffffff166102ed565b6104cb6104c6366004613890565b610e77565b60405161027991906138cb565b610439600081565b6104f36104ee366004613873565b6111b7565b6040516102799190613922565b610508611322565b60405161027991906139a4565b610258610523366004613736565b611333565b61053b610536366004613873565b61144b565b604051610279919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102ed565b6102be6105c3366004613873565b611520565b6102586105d63660046136c7565b6115d0565b6105e36116a4565b60405161027991906139fe565b61053b6105fe366004613873565b61175c565b610258610611366004613b8b565b61182e565b7f00000000000000000000000000000000000000000000000000000000000000006102ed565b6106b061064a366004613873565b60408051606080820183526000808352602080840182905292840181905267ffffffffffffffff949094168452600a82529282902082519384018352805484526001015463ffffffff811691840191909152640100000000900460ff1615159082015290565b604080518251815260208084015163ffffffff169082015291810151151590820152606001610279565b7f000000000000000000000000000000000000000000000000000000000000000061026d565b61025861070e366004613807565b6118b2565b6102586107213660046136c7565b611dc4565b6102ed7f000000000000000000000000000000000000000000000000000000000000000081565b610755611dd8565b60005b818110156108ac57600083838381811061077457610774613bd2565b90506080020180360381019061078a9190613c15565b805190915015806107a75750604081015167ffffffffffffffff16155b1561081657604080517fa087bd2900000000000000000000000000000000000000000000000000000000815282516004820152602083015163ffffffff1660248201529082015167ffffffffffffffff1660448201526060820151151560648201526084015b60405180910390fd5b60408051606080820183528351825260208085015163ffffffff9081168285019081529286015115158486019081529585015167ffffffffffffffff166000908152600a90925293902091518255516001918201805494511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000909516919093161792909217905501610758565b507f1889010d2535a0ab1643678d1da87fbbe8b87b2f585b47ddb72ec622aef9ee5682826040516108de929190613c8f565b60405180910390a15050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061097d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806109c957507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040805160208101909152600081526109e782611e2b565b60006109f660c0840184613d16565b810190610a039190613d7b565b90506000610a1460e0850185613d16565b810190610a219190613e48565b9050610a3181600001518361204f565b805160208201516040517f57ecfd2800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016926357ecfd2892610aa892600401613ed9565b6020604051808303816000875af1158015610ac7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aeb9190613efe565b610b21576040517fbf969f2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b3160608501604086016136c7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08660600135604051610b9391815260200190565b60405180910390a35050604080516020810190915260609092013582525090565b6000610bf68383604051610bc9929190613f1b565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190612200565b949350505050565b610c06611dd8565b610c738484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061221b92505050565b50505050565b610c81611dd8565b610c8a83610e60565b610ccc576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080d565b610d0c8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506123d192505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d62576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610de7611dd8565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006109c9600567ffffffffffffffff8416612200565b6040805180820190915260608082526020820152610e94826124cb565b6000600a81610ea96040860160208701613873565b67ffffffffffffffff168152602080820192909252604090810160002081516060810183528154815260019091015463ffffffff81169382019390935264010000000090920460ff161515908201819052909150610f5057610f116040840160208501613873565b6040517fd201c48a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161080d565b610f5a8380613d16565b9050602014610fa157610f6d8380613d16565b6040517fa3c8cf0900000000000000000000000000000000000000000000000000000000815260040161080d929190613f74565b6000610fad8480613d16565b810190610fba9190613f88565b602083015183516040517ff856ddb60000000000000000000000000000000000000000000000000000000081526060880135600482015263ffffffff90921660248301526044820183905273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116606484015260848301919091529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f856ddb69060a4016020604051808303816000875af115801561109b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bf9190613fa1565b6040516060870135815290915033907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a2604051806040016040528061111c8760200160208101906105c39190613873565b815260408051808201825267ffffffffffffffff851680825263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116602093840190815284518085019390935251169281019290925290910190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905295945050505050565b67ffffffffffffffff81166000908152600760205260408120606091906111e090600501612657565b90506000815167ffffffffffffffff8111156111fe576111fe613a40565b60405190808252806020026020018201604052801561123157816020015b606081526020019060019003908161121c5790505b50905060005b825181101561131a576008600084838151811061125657611256613bd2565b60200260200101518152602001908152602001600020805461127790613fbe565b80601f01602080910402602001604051908101604052809291908181526020018280546112a390613fbe565b80156112f05780601f106112c5576101008083540402835291602001916112f0565b820191906000526020600020905b8154815290600101906020018083116112d357829003601f168201915b505050505082828151811061130757611307613bd2565b6020908102919091010152600101611237565b509392505050565b606061132e6002612657565b905090565b61133b611dd8565b61134483610e60565b611386576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080d565b6113c68282604051611399929190613f1b565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190612664565b611402578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161080d93929190614011565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76838360405161143e929190613f74565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526109c990612670565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061154b90613fbe565b80601f016020809104026020016040519081016040528092919081815260200182805461157790613fbe565b80156115c45780601f10611599576101008083540402835291602001916115c4565b820191906000526020600020905b8154815290600101906020018083116115a757829003601f168201915b50505050509050919050565b6115d8611dd8565b73ffffffffffffffffffffffffffffffffffffffff8116611625576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f168491016108de565b606060006116b26005612657565b90506000815167ffffffffffffffff8111156116d0576116d0613a40565b6040519080825280602002602001820160405280156116f9578160200160208202803683370190505b50905060005b82518110156117555782818151811061171a5761171a613bd2565b602002602001015182828151811061173457611734613bd2565b67ffffffffffffffff909216602092830291909101909101526001016116ff565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526109c990612670565b60095473ffffffffffffffffffffffffffffffffffffffff16331480159061186e575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156118a7576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161080d565b610d0c838383612722565b6118ba611dd8565b60005b83811015611aa75760008585838181106118d9576118d9613bd2565b90506020020160208101906118ee9190613873565b9050611905600567ffffffffffffffff8316612664565b611947576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080d565b67ffffffffffffffff8116600090815260076020526040812061196c90600501612657565b905060005b81518110156119d8576119cf82828151811061198f5761198f613bd2565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161266490919063ffffffff16565b50600101611971565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611a41600483018261350a565b6005820160008181611a538282613544565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991694506020019250611a95915050565b60405180910390a150506001016118bd565b5060005b81811015611dbd576000838383818110611ac757611ac7613bd2565b9050602002810190611ad99190614035565b611ae290614112565b9050611af38160600151600061280c565b611b028160800151600061280c565b806040015151600003611b41576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051611b599060059067ffffffffffffffff16612949565b611b9e5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161080d565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a909102999093161717909416959095179092559092029091176003820155908201516004820190611d21908261421a565b5060005b826020015151811015611d6557611d5d836000015184602001518381518110611d5057611d50613bd2565b60200260200101516123d1565b600101611d25565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c28260000151836040015184606001518560800151604051611dab9493929190614334565b60405180910390a15050600101611aab565b5050505050565b611dcc611dd8565b611dd581612955565b50565b60015473ffffffffffffffffffffffffffffffffffffffff163314611e29576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b611e3e61032060a08301608084016136c7565b611e9d57611e5260a08201608083016136c7565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161080d565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611ee96040840160208501613873565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7e9190613efe565b15611fb5576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611fcd611fc86040830160208401613873565b612a19565b611fed611fe06040830160208401613873565b6103c060a0840184613d16565b61203257611ffe60a0820182613d16565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161080d929190613f74565b611dd56120456040830160208401613873565b8260600135612b3f565b600482015163ffffffff81161561209a576040517f68d2f8d600000000000000000000000000000000000000000000000000000000815263ffffffff8216600482015260240161080d565b6008830151600c8401516014850151602085015163ffffffff8085169116146121055760208501516040517fe366a11700000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161080d565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168263ffffffff161461219a576040517f77e4802600000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301528316602482015260440161080d565b845167ffffffffffffffff8281169116146121f85784516040517ff917ffea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9182166004820152908216602482015260440161080d565b505050505050565b600081815260018301602052604081205415155b9392505050565b7f0000000000000000000000000000000000000000000000000000000000000000612272576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561230857600083828151811061229257612292613bd2565b602002602001015190506122b0816002612b8690919063ffffffff16565b156122ff5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101612275565b5060005b8151811015610d0c57600082828151811061232957612329613bd2565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361236d57506123c9565b612378600282612ba8565b156123c75760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010161230c565b805160000361240c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff841660009081526007909252604090912061243e9060050182612949565b6124785782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161080d9291906143cd565b6000818152600860205260409020612490838261421a565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea8360405161143e9190613692565b6124de61032060a08301608084016136c7565b6124f257611e5260a08201608083016136c7565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb61253e6040840160208501613873565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa1580156125af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d39190613efe565b1561260a576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61262261261d60608301604084016136c7565b612bca565b61263a6126356040830160208401613873565b612c49565b611dd561264d6040830160208401613873565b8260600135612d97565b6060600061221483612ddb565b60006122148383612e36565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526126fe82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426126e2919061441f565b85608001516fffffffffffffffffffffffffffffffff16612f29565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61272b83610e60565b61276d576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080d565b61277882600061280c565b67ffffffffffffffff8316600090815260076020526040902061279b9083612f51565b6127a681600061280c565b67ffffffffffffffff831660009081526007602052604090206127cc9060020182612f51565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516127ff93929190614432565b60405180910390a1505050565b8151156128d75781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612862575060408201516fffffffffffffffffffffffffffffffff16155b1561289b57816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161080d91906144b5565b80156128d3576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612910575060208201516fffffffffffffffffffffffffffffffff1615155b156128d357816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161080d91906144b5565b600061221483836130f3565b3373ffffffffffffffffffffffffffffffffffffffff8216036129a4576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b612a2281610e60565b612a64576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080d565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b079190613efe565b611dd5576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161080d565b67ffffffffffffffff821660009081526007602052604090206128d390600201827f0000000000000000000000000000000000000000000000000000000000000000613142565b60006122148373ffffffffffffffffffffffffffffffffffffffff8416612e36565b60006122148373ffffffffffffffffffffffffffffffffffffffff84166130f3565b7f000000000000000000000000000000000000000000000000000000000000000015611dd557612bfb6002826134c5565b611dd5576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161080d565b612c5281610e60565b612c94576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080d565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3191906144f1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611dd5576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161080d565b67ffffffffffffffff821660009081526007602052604090206128d390827f0000000000000000000000000000000000000000000000000000000000000000613142565b6060816000018054806020026020016040519081016040528092919081815260200182805480156115c457602002820191906000526020600020905b815481526020019060010190808311612e175750505050509050919050565b60008181526001830160205260408120548015612f1f576000612e5a60018361441f565b8554909150600090612e6e9060019061441f565b9050808214612ed3576000866000018281548110612e8e57612e8e613bd2565b9060005260206000200154905080876000018481548110612eb157612eb1613bd2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ee457612ee461450e565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506109c9565b60009150506109c9565b6000612f4885612f39848661453d565b612f439087614554565b6134f4565b95945050505050565b8154600090612f7a90700100000000000000000000000000000000900463ffffffff164261441f565b9050801561301c5760018301548354612fc2916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612f29565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354613042916fffffffffffffffffffffffffffffffff90811691166134f4565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906127ff9084906144b5565b600081815260018301602052604081205461313a575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556109c9565b5060006109c9565b825474010000000000000000000000000000000000000000900460ff161580613169575081155b1561317357505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906131b990700100000000000000000000000000000000900463ffffffff164261441f565b9050801561327957818311156131fb576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546132359083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612f29565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156133305773ffffffffffffffffffffffffffffffffffffffff84166132d8576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161080d565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161080d565b848310156134435760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290613374908261441f565b61337e878a61441f565b6133889190614554565b6133929190614567565b905073ffffffffffffffffffffffffffffffffffffffff86166133eb576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161080d565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161080d565b61344d858461441f565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515612214565b60008183106135035781612214565b5090919050565b50805461351690613fbe565b6000825580601f10613526575050565b601f016020900490600052602060002090810190611dd5919061355e565b5080546000825590600052602060002090810190611dd591905b5b80821115613573576000815560010161355f565b5090565b6000806020838503121561358a57600080fd5b823567ffffffffffffffff808211156135a257600080fd5b818501915085601f8301126135b657600080fd5b8135818111156135c557600080fd5b8660208260071b85010111156135da57600080fd5b60209290920196919550909350505050565b6000602082840312156135fe57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461221457600080fd5b6000815180845260005b8181101561365457602081850181015186830182015201613638565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000612214602083018461362e565b73ffffffffffffffffffffffffffffffffffffffff81168114611dd557600080fd5b6000602082840312156136d957600080fd5b8135612214816136a5565b6000602082840312156136f657600080fd5b813567ffffffffffffffff81111561370d57600080fd5b8201610100818503121561221457600080fd5b67ffffffffffffffff81168114611dd557600080fd5b60008060006040848603121561374b57600080fd5b833561375681613720565b9250602084013567ffffffffffffffff8082111561377357600080fd5b818601915086601f83011261378757600080fd5b81358181111561379657600080fd5b8760208285010111156137a857600080fd5b6020830194508093505050509250925092565b60008083601f8401126137cd57600080fd5b50813567ffffffffffffffff8111156137e557600080fd5b6020830191508360208260051b850101111561380057600080fd5b9250929050565b6000806000806040858703121561381d57600080fd5b843567ffffffffffffffff8082111561383557600080fd5b613841888389016137bb565b9096509450602087013591508082111561385a57600080fd5b50613867878288016137bb565b95989497509550505050565b60006020828403121561388557600080fd5b813561221481613720565b6000602082840312156138a257600080fd5b813567ffffffffffffffff8111156138b957600080fd5b820160a0818503121561221457600080fd5b6020815260008251604060208401526138e7606084018261362e565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612f48828261362e565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613997577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261398585835161362e565b9450928501929085019060010161394b565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156139f257835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016139c0565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156139f257835167ffffffffffffffff1683529284019291840191600101613a1a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613a9257613a92613a40565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613adf57613adf613a40565b604052919050565b8015158114611dd557600080fd5b80356fffffffffffffffffffffffffffffffff81168114613b1557600080fd5b919050565b600060608284031215613b2c57600080fd5b6040516060810181811067ffffffffffffffff82111715613b4f57613b4f613a40565b6040529050808235613b6081613ae7565b8152613b6e60208401613af5565b6020820152613b7f60408401613af5565b60408201525092915050565b600080600060e08486031215613ba057600080fd5b8335613bab81613720565b9250613bba8560208601613b1a565b9150613bc98560808601613b1a565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b803563ffffffff81168114613b1557600080fd5b600060808284031215613c2757600080fd5b6040516080810181811067ffffffffffffffff82111715613c4a57613c4a613a40565b60405282358152613c5d60208401613c01565b60208201526040830135613c7081613720565b60408201526060830135613c8381613ae7565b60608201529392505050565b6020808252818101839052600090604080840186845b87811015613d09578135835263ffffffff613cc1868401613c01565b168584015283820135613cd381613720565b67ffffffffffffffff1683850152606082810135613cf081613ae7565b1515908401526080928301929190910190600101613ca5565b5090979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613d4b57600080fd5b83018035915067ffffffffffffffff821115613d6657600080fd5b60200191503681900382131561380057600080fd5b600060408284031215613d8d57600080fd5b613d95613a6f565b8235613da081613720565b8152613dae60208401613c01565b60208201529392505050565b600082601f830112613dcb57600080fd5b813567ffffffffffffffff811115613de557613de5613a40565b613e1660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613a98565b818152846020838601011115613e2b57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613e5a57600080fd5b813567ffffffffffffffff80821115613e7257600080fd5b9083019060408286031215613e8657600080fd5b613e8e613a6f565b823582811115613e9d57600080fd5b613ea987828601613dba565b825250602083013582811115613ebe57600080fd5b613eca87828601613dba565b60208301525095945050505050565b604081526000613eec604083018561362e565b8281036020840152612f48818561362e565b600060208284031215613f1057600080fd5b815161221481613ae7565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000610bf6602083018486613f2b565b600060208284031215613f9a57600080fd5b5035919050565b600060208284031215613fb357600080fd5b815161221481613720565b600181811c90821680613fd257607f821691505b60208210810361400b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b67ffffffffffffffff84168152604060208201526000612f48604083018486613f2b565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261406957600080fd5b9190910192915050565b600082601f83011261408457600080fd5b8135602067ffffffffffffffff808311156140a1576140a1613a40565b8260051b6140b0838201613a98565b93845285810183019383810190888611156140ca57600080fd5b84880192505b85831015614106578235848111156140e85760008081fd5b6140f68a87838c0101613dba565b83525091840191908401906140d0565b98975050505050505050565b6000610120823603121561412557600080fd5b60405160a0810167ffffffffffffffff828210818311171561414957614149613a40565b816040528435915061415a82613720565b9082526020840135908082111561417057600080fd5b61417c36838701614073565b6020840152604085013591508082111561419557600080fd5b506141a236828601613dba565b6040830152506141b53660608501613b1a565b60608201526141c73660c08501613b1a565b608082015292915050565b601f821115610d0c576000816000526020600020601f850160051c810160208610156141fb5750805b601f850160051c820191505b818110156121f857828155600101614207565b815167ffffffffffffffff81111561423457614234613a40565b614248816142428454613fbe565b846141d2565b602080601f83116001811461429b57600084156142655750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556121f8565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156142e8578886015182559484019460019091019084016142c9565b508582101561432457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526143588184018761362e565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506143969050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612f48565b67ffffffffffffffff83168152604060208201526000610bf6604083018461362e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156109c9576109c96143f0565b67ffffffffffffffff8416815260e0810161447e60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610bf6565b606081016109c982848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561450357600080fd5b8151612214816136a5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b80820281158282048414176109c9576109c96143f0565b808201808211156109c9576109c96143f0565b60008261459d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"tokenMessenger\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidDestinationDomain\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate\",\"name\":\"domain\",\"type\":\"tuple\"}],\"name\":\"InvalidDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidMessageVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"}],\"name\":\"InvalidNonce\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"}],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidSourceDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidTokenMessengerVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"domain\",\"type\":\"uint64\"}],\"name\":\"UnknownDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnlockingUSDCFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenMessenger\",\"type\":\"address\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"name\":\"DomainsSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"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\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SUPPORTED_USDC_VERSION\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getDomain\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.Domain\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_localDomainIdentifier\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_messageTransmitter\",\"outputs\":[{\"internalType\":\"contractIMessageTransmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_tokenMessenger\",\"outputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"domains\",\"type\":\"tuple[]\"}],\"name\":\"setDomains\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101606040523480156200001257600080fd5b50604051620054b7380380620054b7833981016040819052620000359162000b93565b836006848484336000816200005d57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200009057620000908162000493565b50506001600160a01b0385161580620000b057506001600160a01b038116155b80620000c357506001600160a01b038216155b15620000e2576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000152575060408051601f3d908101601f191682019092526200014f9181019062000cb9565b60015b1562000193578060ff168560ff161462000191576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dd57604080516000815260208101909152620001dd90846200050d565b5050506001600160a01b03871691506200020c9050576040516306b7c75960e31b815260040160405180910390fd5b6000856001600160a01b0316632c1219216040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200024d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000273919062000ce5565b90506000816001600160a01b03166354fd4d506040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002b6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002dc919062000d05565b905063ffffffff8116156200030d576040516334697c6b60e11b815263ffffffff8216600482015260240162000188565b6000876001600160a01b0316639cdbb1816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200034e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000374919062000d05565b905063ffffffff811615620003a5576040516316ba39c560e31b815263ffffffff8216600482015260240162000188565b6001600160a01b038089166101005283166101208190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa158015620003f8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200041e919062000d05565b63ffffffff16610140526101005160805162000449916001600160a01b03909116906000196200066a565b6040516001600160a01b03891681527f2e902d38f15b233cbb63711add0fca4545334d3a169d60c0a616494d7eea95449060200160405180910390a1505050505050505062000e52565b336001600160a01b03821603620004bd57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e0516200052e576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620005b957600083828151811062000552576200055262000d2d565b602090810291909101015190506200056c60028262000750565b15620005af576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000531565b5060005b815181101562000665576000828281518110620005de57620005de62000d2d565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200060a57506200065c565b6200061760028262000770565b156200065a576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620005bd565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620006bc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006e2919062000d43565b620006ee919062000d73565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200074a918691906200078716565b50505050565b600062000767836001600160a01b03841662000858565b90505b92915050565b600062000767836001600160a01b0384166200095c565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490820152600090620007d6906001600160a01b038516908490620009ae565b805190915015620006655780806020019051810190620007f7919062000d89565b620006655760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000188565b60008181526001830160205260408120548015620009515760006200087f60018362000dad565b8554909150600090620008959060019062000dad565b905080821462000901576000866000018281548110620008b957620008b962000d2d565b9060005260206000200154905080876000018481548110620008df57620008df62000d2d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000915576200091562000dc3565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200076a565b60009150506200076a565b6000818152600183016020526040812054620009a5575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200076a565b5060006200076a565b6060620009bf8484600085620009c7565b949350505050565b60608247101562000a2a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000188565b600080866001600160a01b0316858760405162000a48919062000dff565b60006040518083038185875af1925050503d806000811462000a87576040519150601f19603f3d011682016040523d82523d6000602084013e62000a8c565b606091505b50909250905062000aa08783838762000aab565b979650505050505050565b6060831562000b1f57825160000362000b17576001600160a01b0385163b62000b175760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000188565b5081620009bf565b620009bf838381511562000b365781518083602001fd5b8060405162461bcd60e51b815260040162000188919062000e1d565b6001600160a01b038116811462000b6857600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000b8e8162000b52565b919050565b600080600080600060a0868803121562000bac57600080fd5b855162000bb98162000b52565b8095505060208087015162000bce8162000b52565b60408801519095506001600160401b038082111562000bec57600080fd5b818901915089601f83011262000c0157600080fd5b81518181111562000c165762000c1662000b6b565b8060051b604051601f19603f8301168101818110858211171562000c3e5762000c3e62000b6b565b60405291825284820192508381018501918c83111562000c5d57600080fd5b938501935b8285101562000c865762000c768562000b81565b8452938501939285019262000c62565b80985050505050505062000c9d6060870162000b81565b915062000cad6080870162000b81565b90509295509295909350565b60006020828403121562000ccc57600080fd5b815160ff8116811462000cde57600080fd5b9392505050565b60006020828403121562000cf857600080fd5b815162000cde8162000b52565b60006020828403121562000d1857600080fd5b815163ffffffff8116811462000cde57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000d5657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156200076a576200076a62000d5d565b60006020828403121562000d9c57600080fd5b8151801515811462000cde57600080fd5b818103818111156200076a576200076a62000d5d565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000df657818101518382015260200162000ddc565b50506000910152565b6000825162000e1381846020870162000dd9565b9190910192915050565b602081526000825180602084015262000e3e81604085016020870162000dd9565b601f01601f19169190910160400192915050565b60805160a05160c05160e0516101005161012051610140516145af62000f08600039600081816104170152818161113c01528181612107015261216501526000818161072b0152610a750152600081816103dd01526110520152600081816106dc0152818161221d0152612bcc01526000818161061801528181611eb40152612509015260006103660152600081816102cd015281816103220152818161101c01528181612b620152612db701526145af6000f3fe608060405234801561001057600080fd5b50600436106102405760003560e01c80639a4575b911610145578063c4bffe2b116100bd578063dfadfa351161008c578063e8a1da1711610071578063e8a1da1714610700578063f2fde38b14610713578063fbf84dd71461072657600080fd5b8063dfadfa351461063c578063e0351e13146106da57600080fd5b8063c4bffe2b146105db578063c75eea9c146105f0578063cf7401f314610603578063dc0bd9711461061657600080fd5b8063acfecf9111610114578063b0f479a1116100f9578063b0f479a114610597578063b7946580146105b5578063c0d78655146105c857600080fd5b8063acfecf9114610515578063af58d59f1461052857600080fd5b80639a4575b9146104b85780639fdf13ff146104d8578063a42a7b8b146104e0578063a7cd63b71461050057600080fd5b806354c8a4f3116101d85780636d3d1a58116101a75780637d54534e1161018c5780637d54534e146104745780638926f54f146104875780638da5cb5b1461049a57600080fd5b80636d3d1a581461044e57806379ba50971461046c57600080fd5b806354c8a4f3146103c55780636155cda0146103d857806362ddd3c4146103ff5780636b716b0d1461041257600080fd5b8063240028e811610214578063240028e81461031257806324f65ee71461035f57806339077537146103905780634c5ef0ed146103b257600080fd5b806241d3c11461024557806301ffc9a71461025a578063181f5a771461028257806321df0da7146102cb575b600080fd5b610258610253366004613577565b61074d565b005b61026d6102683660046135ec565b6108ea565b60405190151581526020015b60405180910390f35b6102be6040518060400160405280601381526020017f55534443546f6b656e506f6f6c20312e352e310000000000000000000000000081525081565b6040516102799190613692565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610279565b61026d6103203660046136c7565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610279565b6103a361039e3660046136e4565b6109cf565b60405190518152602001610279565b61026d6103c0366004613736565b610bb4565b6102586103d3366004613807565b610bfe565b6102ed7f000000000000000000000000000000000000000000000000000000000000000081565b61025861040d366004613736565b610c79565b6104397f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610279565b60095473ffffffffffffffffffffffffffffffffffffffff166102ed565b610258610d11565b6102586104823660046136c7565b610ddf565b61026d610495366004613873565b610e60565b60015473ffffffffffffffffffffffffffffffffffffffff166102ed565b6104cb6104c6366004613890565b610e77565b60405161027991906138cb565b610439600081565b6104f36104ee366004613873565b6111b7565b6040516102799190613922565b610508611322565b60405161027991906139a4565b610258610523366004613736565b611333565b61053b610536366004613873565b61144b565b604051610279919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102ed565b6102be6105c3366004613873565b611520565b6102586105d63660046136c7565b6115d0565b6105e36116a4565b60405161027991906139fe565b61053b6105fe366004613873565b61175c565b610258610611366004613b8b565b61182e565b7f00000000000000000000000000000000000000000000000000000000000000006102ed565b6106b061064a366004613873565b60408051606080820183526000808352602080840182905292840181905267ffffffffffffffff949094168452600a82529282902082519384018352805484526001015463ffffffff811691840191909152640100000000900460ff1615159082015290565b604080518251815260208084015163ffffffff169082015291810151151590820152606001610279565b7f000000000000000000000000000000000000000000000000000000000000000061026d565b61025861070e366004613807565b6118b2565b6102586107213660046136c7565b611dc4565b6102ed7f000000000000000000000000000000000000000000000000000000000000000081565b610755611dd8565b60005b818110156108ac57600083838381811061077457610774613bd2565b90506080020180360381019061078a9190613c15565b805190915015806107a75750604081015167ffffffffffffffff16155b1561081657604080517fa087bd2900000000000000000000000000000000000000000000000000000000815282516004820152602083015163ffffffff1660248201529082015167ffffffffffffffff1660448201526060820151151560648201526084015b60405180910390fd5b60408051606080820183528351825260208085015163ffffffff9081168285019081529286015115158486019081529585015167ffffffffffffffff166000908152600a90925293902091518255516001918201805494511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000909516919093161792909217905501610758565b507f1889010d2535a0ab1643678d1da87fbbe8b87b2f585b47ddb72ec622aef9ee5682826040516108de929190613c8f565b60405180910390a15050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061097d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806109c957507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040805160208101909152600081526109e782611e2b565b60006109f660c0840184613d16565b810190610a039190613d7b565b90506000610a1460e0850185613d16565b810190610a219190613e48565b9050610a3181600001518361204f565b805160208201516040517f57ecfd2800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016926357ecfd2892610aa892600401613ed9565b6020604051808303816000875af1158015610ac7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aeb9190613efe565b610b21576040517fbf969f2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b3160608501604086016136c7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08660600135604051610b9391815260200190565b60405180910390a35050604080516020810190915260609092013582525090565b6000610bf68383604051610bc9929190613f1b565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190612200565b949350505050565b610c06611dd8565b610c738484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061221b92505050565b50505050565b610c81611dd8565b610c8a83610e60565b610ccc576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080d565b610d0c8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506123d192505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d62576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610de7611dd8565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006109c9600567ffffffffffffffff8416612200565b6040805180820190915260608082526020820152610e94826124cb565b6000600a81610ea96040860160208701613873565b67ffffffffffffffff168152602080820192909252604090810160002081516060810183528154815260019091015463ffffffff81169382019390935264010000000090920460ff161515908201819052909150610f5057610f116040840160208501613873565b6040517fd201c48a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161080d565b610f5a8380613d16565b9050602014610fa157610f6d8380613d16565b6040517fa3c8cf0900000000000000000000000000000000000000000000000000000000815260040161080d929190613f74565b6000610fad8480613d16565b810190610fba9190613f88565b602083015183516040517ff856ddb60000000000000000000000000000000000000000000000000000000081526060880135600482015263ffffffff90921660248301526044820183905273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116606484015260848301919091529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f856ddb69060a4016020604051808303816000875af115801561109b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bf9190613fa1565b6040516060870135815290915033907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a2604051806040016040528061111c8760200160208101906105c39190613873565b815260408051808201825267ffffffffffffffff851680825263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116602093840190815284518085019390935251169281019290925290910190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905295945050505050565b67ffffffffffffffff81166000908152600760205260408120606091906111e090600501612657565b90506000815167ffffffffffffffff8111156111fe576111fe613a40565b60405190808252806020026020018201604052801561123157816020015b606081526020019060019003908161121c5790505b50905060005b825181101561131a576008600084838151811061125657611256613bd2565b60200260200101518152602001908152602001600020805461127790613fbe565b80601f01602080910402602001604051908101604052809291908181526020018280546112a390613fbe565b80156112f05780601f106112c5576101008083540402835291602001916112f0565b820191906000526020600020905b8154815290600101906020018083116112d357829003601f168201915b505050505082828151811061130757611307613bd2565b6020908102919091010152600101611237565b509392505050565b606061132e6002612657565b905090565b61133b611dd8565b61134483610e60565b611386576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080d565b6113c68282604051611399929190613f1b565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190612664565b611402578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161080d93929190614011565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76838360405161143e929190613f74565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526109c990612670565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061154b90613fbe565b80601f016020809104026020016040519081016040528092919081815260200182805461157790613fbe565b80156115c45780601f10611599576101008083540402835291602001916115c4565b820191906000526020600020905b8154815290600101906020018083116115a757829003601f168201915b50505050509050919050565b6115d8611dd8565b73ffffffffffffffffffffffffffffffffffffffff8116611625576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f168491016108de565b606060006116b26005612657565b90506000815167ffffffffffffffff8111156116d0576116d0613a40565b6040519080825280602002602001820160405280156116f9578160200160208202803683370190505b50905060005b82518110156117555782818151811061171a5761171a613bd2565b602002602001015182828151811061173457611734613bd2565b67ffffffffffffffff909216602092830291909101909101526001016116ff565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526109c990612670565b60095473ffffffffffffffffffffffffffffffffffffffff16331480159061186e575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156118a7576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161080d565b610d0c838383612722565b6118ba611dd8565b60005b83811015611aa75760008585838181106118d9576118d9613bd2565b90506020020160208101906118ee9190613873565b9050611905600567ffffffffffffffff8316612664565b611947576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080d565b67ffffffffffffffff8116600090815260076020526040812061196c90600501612657565b905060005b81518110156119d8576119cf82828151811061198f5761198f613bd2565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161266490919063ffffffff16565b50600101611971565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611a41600483018261350a565b6005820160008181611a538282613544565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991694506020019250611a95915050565b60405180910390a150506001016118bd565b5060005b81811015611dbd576000838383818110611ac757611ac7613bd2565b9050602002810190611ad99190614035565b611ae290614112565b9050611af38160600151600061280c565b611b028160800151600061280c565b806040015151600003611b41576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051611b599060059067ffffffffffffffff16612949565b611b9e5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161080d565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a909102999093161717909416959095179092559092029091176003820155908201516004820190611d21908261421a565b5060005b826020015151811015611d6557611d5d836000015184602001518381518110611d5057611d50613bd2565b60200260200101516123d1565b600101611d25565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c28260000151836040015184606001518560800151604051611dab9493929190614334565b60405180910390a15050600101611aab565b5050505050565b611dcc611dd8565b611dd581612955565b50565b60015473ffffffffffffffffffffffffffffffffffffffff163314611e29576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b611e3e61032060a08301608084016136c7565b611e9d57611e5260a08201608083016136c7565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161080d565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611ee96040840160208501613873565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7e9190613efe565b15611fb5576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611fcd611fc86040830160208401613873565b612a19565b611fed611fe06040830160208401613873565b6103c060a0840184613d16565b61203257611ffe60a0820182613d16565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161080d929190613f74565b611dd56120456040830160208401613873565b8260600135612b3f565b600482015163ffffffff81161561209a576040517f68d2f8d600000000000000000000000000000000000000000000000000000000815263ffffffff8216600482015260240161080d565b6008830151600c8401516014850151602085015163ffffffff8085169116146121055760208501516040517fe366a11700000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161080d565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168263ffffffff161461219a576040517f77e4802600000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301528316602482015260440161080d565b845167ffffffffffffffff8281169116146121f85784516040517ff917ffea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9182166004820152908216602482015260440161080d565b505050505050565b600081815260018301602052604081205415155b9392505050565b7f0000000000000000000000000000000000000000000000000000000000000000612272576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561230857600083828151811061229257612292613bd2565b602002602001015190506122b0816002612b8690919063ffffffff16565b156122ff5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101612275565b5060005b8151811015610d0c57600082828151811061232957612329613bd2565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361236d57506123c9565b612378600282612ba8565b156123c75760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010161230c565b805160000361240c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff841660009081526007909252604090912061243e9060050182612949565b6124785782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161080d9291906143cd565b6000818152600860205260409020612490838261421a565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea8360405161143e9190613692565b6124de61032060a08301608084016136c7565b6124f257611e5260a08201608083016136c7565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb61253e6040840160208501613873565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa1580156125af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d39190613efe565b1561260a576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61262261261d60608301604084016136c7565b612bca565b61263a6126356040830160208401613873565b612c49565b611dd561264d6040830160208401613873565b8260600135612d97565b6060600061221483612ddb565b60006122148383612e36565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526126fe82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426126e2919061441f565b85608001516fffffffffffffffffffffffffffffffff16612f29565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61272b83610e60565b61276d576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080d565b61277882600061280c565b67ffffffffffffffff8316600090815260076020526040902061279b9083612f51565b6127a681600061280c565b67ffffffffffffffff831660009081526007602052604090206127cc9060020182612f51565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516127ff93929190614432565b60405180910390a1505050565b8151156128d75781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612862575060408201516fffffffffffffffffffffffffffffffff16155b1561289b57816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161080d91906144b5565b80156128d3576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612910575060208201516fffffffffffffffffffffffffffffffff1615155b156128d357816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161080d91906144b5565b600061221483836130f3565b3373ffffffffffffffffffffffffffffffffffffffff8216036129a4576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b612a2281610e60565b612a64576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080d565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b079190613efe565b611dd5576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161080d565b67ffffffffffffffff821660009081526007602052604090206128d390600201827f0000000000000000000000000000000000000000000000000000000000000000613142565b60006122148373ffffffffffffffffffffffffffffffffffffffff8416612e36565b60006122148373ffffffffffffffffffffffffffffffffffffffff84166130f3565b7f000000000000000000000000000000000000000000000000000000000000000015611dd557612bfb6002826134c5565b611dd5576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161080d565b612c5281610e60565b612c94576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080d565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3191906144f1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611dd5576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161080d565b67ffffffffffffffff821660009081526007602052604090206128d390827f0000000000000000000000000000000000000000000000000000000000000000613142565b6060816000018054806020026020016040519081016040528092919081815260200182805480156115c457602002820191906000526020600020905b815481526020019060010190808311612e175750505050509050919050565b60008181526001830160205260408120548015612f1f576000612e5a60018361441f565b8554909150600090612e6e9060019061441f565b9050808214612ed3576000866000018281548110612e8e57612e8e613bd2565b9060005260206000200154905080876000018481548110612eb157612eb1613bd2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ee457612ee461450e565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506109c9565b60009150506109c9565b6000612f4885612f39848661453d565b612f439087614554565b6134f4565b95945050505050565b8154600090612f7a90700100000000000000000000000000000000900463ffffffff164261441f565b9050801561301c5760018301548354612fc2916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612f29565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354613042916fffffffffffffffffffffffffffffffff90811691166134f4565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906127ff9084906144b5565b600081815260018301602052604081205461313a575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556109c9565b5060006109c9565b825474010000000000000000000000000000000000000000900460ff161580613169575081155b1561317357505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906131b990700100000000000000000000000000000000900463ffffffff164261441f565b9050801561327957818311156131fb576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546132359083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612f29565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156133305773ffffffffffffffffffffffffffffffffffffffff84166132d8576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161080d565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161080d565b848310156134435760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290613374908261441f565b61337e878a61441f565b6133889190614554565b6133929190614567565b905073ffffffffffffffffffffffffffffffffffffffff86166133eb576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161080d565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161080d565b61344d858461441f565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515612214565b60008183106135035781612214565b5090919050565b50805461351690613fbe565b6000825580601f10613526575050565b601f016020900490600052602060002090810190611dd5919061355e565b5080546000825590600052602060002090810190611dd591905b5b80821115613573576000815560010161355f565b5090565b6000806020838503121561358a57600080fd5b823567ffffffffffffffff808211156135a257600080fd5b818501915085601f8301126135b657600080fd5b8135818111156135c557600080fd5b8660208260071b85010111156135da57600080fd5b60209290920196919550909350505050565b6000602082840312156135fe57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461221457600080fd5b6000815180845260005b8181101561365457602081850181015186830182015201613638565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000612214602083018461362e565b73ffffffffffffffffffffffffffffffffffffffff81168114611dd557600080fd5b6000602082840312156136d957600080fd5b8135612214816136a5565b6000602082840312156136f657600080fd5b813567ffffffffffffffff81111561370d57600080fd5b8201610100818503121561221457600080fd5b67ffffffffffffffff81168114611dd557600080fd5b60008060006040848603121561374b57600080fd5b833561375681613720565b9250602084013567ffffffffffffffff8082111561377357600080fd5b818601915086601f83011261378757600080fd5b81358181111561379657600080fd5b8760208285010111156137a857600080fd5b6020830194508093505050509250925092565b60008083601f8401126137cd57600080fd5b50813567ffffffffffffffff8111156137e557600080fd5b6020830191508360208260051b850101111561380057600080fd5b9250929050565b6000806000806040858703121561381d57600080fd5b843567ffffffffffffffff8082111561383557600080fd5b613841888389016137bb565b9096509450602087013591508082111561385a57600080fd5b50613867878288016137bb565b95989497509550505050565b60006020828403121561388557600080fd5b813561221481613720565b6000602082840312156138a257600080fd5b813567ffffffffffffffff8111156138b957600080fd5b820160a0818503121561221457600080fd5b6020815260008251604060208401526138e7606084018261362e565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612f48828261362e565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613997577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261398585835161362e565b9450928501929085019060010161394b565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156139f257835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016139c0565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156139f257835167ffffffffffffffff1683529284019291840191600101613a1a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613a9257613a92613a40565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613adf57613adf613a40565b604052919050565b8015158114611dd557600080fd5b80356fffffffffffffffffffffffffffffffff81168114613b1557600080fd5b919050565b600060608284031215613b2c57600080fd5b6040516060810181811067ffffffffffffffff82111715613b4f57613b4f613a40565b6040529050808235613b6081613ae7565b8152613b6e60208401613af5565b6020820152613b7f60408401613af5565b60408201525092915050565b600080600060e08486031215613ba057600080fd5b8335613bab81613720565b9250613bba8560208601613b1a565b9150613bc98560808601613b1a565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b803563ffffffff81168114613b1557600080fd5b600060808284031215613c2757600080fd5b6040516080810181811067ffffffffffffffff82111715613c4a57613c4a613a40565b60405282358152613c5d60208401613c01565b60208201526040830135613c7081613720565b60408201526060830135613c8381613ae7565b60608201529392505050565b6020808252818101839052600090604080840186845b87811015613d09578135835263ffffffff613cc1868401613c01565b168584015283820135613cd381613720565b67ffffffffffffffff1683850152606082810135613cf081613ae7565b1515908401526080928301929190910190600101613ca5565b5090979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613d4b57600080fd5b83018035915067ffffffffffffffff821115613d6657600080fd5b60200191503681900382131561380057600080fd5b600060408284031215613d8d57600080fd5b613d95613a6f565b8235613da081613720565b8152613dae60208401613c01565b60208201529392505050565b600082601f830112613dcb57600080fd5b813567ffffffffffffffff811115613de557613de5613a40565b613e1660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613a98565b818152846020838601011115613e2b57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613e5a57600080fd5b813567ffffffffffffffff80821115613e7257600080fd5b9083019060408286031215613e8657600080fd5b613e8e613a6f565b823582811115613e9d57600080fd5b613ea987828601613dba565b825250602083013582811115613ebe57600080fd5b613eca87828601613dba565b60208301525095945050505050565b604081526000613eec604083018561362e565b8281036020840152612f48818561362e565b600060208284031215613f1057600080fd5b815161221481613ae7565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000610bf6602083018486613f2b565b600060208284031215613f9a57600080fd5b5035919050565b600060208284031215613fb357600080fd5b815161221481613720565b600181811c90821680613fd257607f821691505b60208210810361400b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b67ffffffffffffffff84168152604060208201526000612f48604083018486613f2b565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261406957600080fd5b9190910192915050565b600082601f83011261408457600080fd5b8135602067ffffffffffffffff808311156140a1576140a1613a40565b8260051b6140b0838201613a98565b93845285810183019383810190888611156140ca57600080fd5b84880192505b85831015614106578235848111156140e85760008081fd5b6140f68a87838c0101613dba565b83525091840191908401906140d0565b98975050505050505050565b6000610120823603121561412557600080fd5b60405160a0810167ffffffffffffffff828210818311171561414957614149613a40565b816040528435915061415a82613720565b9082526020840135908082111561417057600080fd5b61417c36838701614073565b6020840152604085013591508082111561419557600080fd5b506141a236828601613dba565b6040830152506141b53660608501613b1a565b60608201526141c73660c08501613b1a565b608082015292915050565b601f821115610d0c576000816000526020600020601f850160051c810160208610156141fb5750805b601f850160051c820191505b818110156121f857828155600101614207565b815167ffffffffffffffff81111561423457614234613a40565b614248816142428454613fbe565b846141d2565b602080601f83116001811461429b57600084156142655750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556121f8565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156142e8578886015182559484019460019091019084016142c9565b508582101561432457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526143588184018761362e565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506143969050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612f48565b67ffffffffffffffff83168152604060208201526000610bf6604083018461362e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156109c9576109c96143f0565b67ffffffffffffffff8416815260e0810161447e60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610bf6565b606081016109c982848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561450357600080fd5b8151612214816136a5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b80820281158282048414176109c9576109c96143f0565b808201808211156109c9576109c96143f0565b60008261459d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", } var USDCTokenPoolABI = USDCTokenPoolMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 5d381c6db67..dd2799ba810 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,32 +1,32 @@ GETH_VERSION: 1.14.11 -burn_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin 3be84751a3c43b6a8522e67368b69e1ec1b4271768c4c0fd9542ade23ce33306 -burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin f44a858fed054ede21ae4af7ca66006c0993d9980b641dae2c6d3dc08471c936 -burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 0b825a9ea058cf2c72b75996bfe0e69f92e0e36b9af674abfe8fd036f5fa1a2c +burn_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin 642919607d5642aa98713b88f737c918487adba682535cf630b7c7d5fd80dc43 +burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin 054d95f302a142f7b64eea27237e0889bee6c9eb8a487579c7279c09646dc42b +burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin c3f723e7f6394297c095a9d9696f1bceec4a2e85b5be2159f7a21d257eb6b480 ccip_encoding_utils: ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.bin 9971fc93c34442a0989570d3dab90a125de31e6e60754ad972807ce6ad4dfba0 ccip_home: ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.abi ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.bin 02cb75b4274a5be7f4006cf2b72cc09e77eb6dba4c1a9c720af86668ff8ea1df -ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 893c9930e874fe5235db24e28a22650c37f562da94fac93618566bcd84839fdc +ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin b368699ae7dbee7c21d049a641642837f18ce2cc8d4ece69509f205de673108e ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de -fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 8a0869d14bb5247fbc6d836fc20d123358373ed688e0d3b387d59e7d05496fea -lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin 26dd99fa523446ff6857898d3aa14976660b4307a753de82541362a9ae33f292 +fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin aee49c9246d5903e68b175516b3cdfdec5df23e25d53d604cd382b6bc0bf34f7 +lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin 1067f557abeb5570f1da7f050ea982ffad0f35dc064e668a8a0e6af128df490c maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin ec2d3a92348d8e7b8f0d359b62a45157b9d2c750c01fbcf991826c4392f6e218 mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin d976651d36b33ac2196b32b9d2f4fa6690c6a18d41b621365659fce1c1d1e737 mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin be0dbc3e475741ea0b7a54ec2b935a321b428baa9f4ce18180a87fb38bb87de2 mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin c3cac2010c2815b484055bf981363a2bd04e7fbe7bb502dc8fd29a16165d221c -multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 79bfbd1f7d3c2aeee6301ae1275c39924a0b41f16b051d1c0046d3fc4265093d +multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin a523e11ea4c069d7d61b309c156951cc6834aff0f352bd1ac37c3a838ff2588f nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin e6008490d916826cefd1903612db39621d51617300fc9bb42b68c6c117958198 -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin d20e6c0baf08926b341c31ed0018983e135a75b7d120591de49ca4ece3824d0b +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 7c65e586181c5099a6ecb5353f60043bb6add9ebad941ddf7ef9998c7ee008ea onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 2bf74188a997218502031f177cb2df505b272d66b25fd341a741289e77380c59 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin 24b4415a883a470d65c484be0fa20714a46b1c9262db205f1c958017820307b2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 0fc277a0b512db4e20b5a32a775b94ed2c0d342d8237511de78c94f7dacad428 report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 6c943b39f003aa67c3cefa19a8ff99e846236a058e1ceae77569c3a065ffd5c7 rmn_home: ../../../contracts/solc/v0.8.24/RMNHome/RMNHome.abi ../../../contracts/solc/v0.8.24/RMNHome/RMNHome.bin 84ca84b3d0c00949905a3d10a91255f877cf32b2a0d7f7f7ce3121ced34a8cb7 rmn_proxy_contract: ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin b048d8e752e3c41113ebb305c1efa06737ad36b4907b93e627fb0a3113023454 -rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin faee0b0cdbe67f2e28deccf12acd4df13dd90992f6cbc0ba17bab845b8f4eb1c +rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin 941118dfdc6bb042c339cfe8d8e0c7a0b486afb731a785d58a64994e7a13c459 router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 2e4f0a7826c8abb49d882bb49fc5ff20a186dbd3137624b9097ffed903ae4888 token_admin_registry: ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin 397bc7be08c2848c0f4715f90b16206d6367f78ffb7cd48e2b1dfc0ccc5aea26 -token_pool: ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin e2d55e56f5401e8cb52fbf4c7dbc477548b5ca2f1d6a28561ebd523f42113c55 +token_pool: ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin da86a1407f31134e7246bde63c80ce8c78ce7d7b44e267f3c1f6030441ff4252 usdc_reader_tester: ../../../contracts/solc/v0.8.24/USDCReaderTester/USDCReaderTester.abi ../../../contracts/solc/v0.8.24/USDCReaderTester/USDCReaderTester.bin 672a07c9218fd6ad7c04dde583088b0f5ffc8d55a46f4be1714008dd3409438b -usdc_token_pool: ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin 0e49d3f0a8420c81a2136dbba66ed988a8ec0e975799e7c8ba83d163bb45313a +usdc_token_pool: ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin b688126b13353f7aab7481f3f6b8f79cd2cace96be71eace70237d402823493a weth9: ../../../contracts/solc/v0.8.24/WETH9/WETH9.abi ../../../contracts/solc/v0.8.24/WETH9/WETH9.bin 2970d79a0ca6dd6279cde130de45e56c8790ed695eae477fb5ba4c1bb75b720d diff --git a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go index 7c0f421526e..8fadeb40e08 100644 --- a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go +++ b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go @@ -3416,6 +3416,63 @@ func (_c *FeeQuoterInterface_SetReportPermissions_Call) RunAndReturn(run func(*b return _c } +// SupportsInterface provides a mock function with given fields: opts, interfaceId +func (_m *FeeQuoterInterface) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + ret := _m.Called(opts, interfaceId) + + if len(ret) == 0 { + panic("no return value specified for SupportsInterface") + } + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, [4]byte) (bool, error)); ok { + return rf(opts, interfaceId) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, [4]byte) bool); ok { + r0 = rf(opts, interfaceId) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, [4]byte) error); ok { + r1 = rf(opts, interfaceId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_SupportsInterface_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SupportsInterface' +type FeeQuoterInterface_SupportsInterface_Call struct { + *mock.Call +} + +// SupportsInterface is a helper method to define mock.On call +// - opts *bind.CallOpts +// - interfaceId [4]byte +func (_e *FeeQuoterInterface_Expecter) SupportsInterface(opts interface{}, interfaceId interface{}) *FeeQuoterInterface_SupportsInterface_Call { + return &FeeQuoterInterface_SupportsInterface_Call{Call: _e.mock.On("SupportsInterface", opts, interfaceId)} +} + +func (_c *FeeQuoterInterface_SupportsInterface_Call) Run(run func(opts *bind.CallOpts, interfaceId [4]byte)) *FeeQuoterInterface_SupportsInterface_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].([4]byte)) + }) + return _c +} + +func (_c *FeeQuoterInterface_SupportsInterface_Call) Return(_a0 bool, _a1 error) *FeeQuoterInterface_SupportsInterface_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_SupportsInterface_Call) RunAndReturn(run func(*bind.CallOpts, [4]byte) (bool, error)) *FeeQuoterInterface_SupportsInterface_Call { + _c.Call.Return(run) + return _c +} + // TransferOwnership provides a mock function with given fields: opts, to func (_m *FeeQuoterInterface) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { ret := _m.Called(opts, to) diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 554b11b5aa8..7ade85f4bf7 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -452,6 +452,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn solanaCfg := chainlink.SolanaFactoryConfig{ Keystore: keyStore.Solana(), TOMLConfigs: cfg.SolanaConfigs(), + DS: ds, } initOps = append(initOps, chainlink.InitSolana(ctx, relayerFactory, solanaCfg)) } diff --git a/core/logger/null_logger.go b/core/logger/null_logger.go index 9bddd9b336f..e3e841e138c 100644 --- a/core/logger/null_logger.go +++ b/core/logger/null_logger.go @@ -4,7 +4,6 @@ import ( "go.uber.org/zap/zapcore" ) -// nolint var NullLogger Logger = &nullLogger{} type nullLogger struct{} diff --git a/core/scripts/go.mod b/core/scripts/go.mod index e1f87de6f5e..8f9e458b8e2 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -1,6 +1,8 @@ module github.com/smartcontractkit/chainlink/core/scripts -go 1.23 +go 1.23.3 + +toolchain go1.23.4 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../../ @@ -24,7 +26,7 @@ require ( github.com/prometheus/client_golang v1.20.5 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241106193309-5560cd76211a github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 @@ -236,7 +238,7 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a // indirect + github.com/leanovate/gopter v0.2.11 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect @@ -265,7 +267,6 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/run v1.1.0 // indirect github.com/onsi/ginkgo/v2 v2.20.1 // indirect - github.com/onsi/gomega v1.34.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect @@ -296,19 +297,20 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 // indirect - github.com/smartcontractkit/chain-selectors v1.0.31 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57 // indirect + github.com/smartcontractkit/chain-selectors v1.0.34 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 // indirect - github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect - github.com/smartcontractkit/wsrpc v0.8.2 // indirect + github.com/smartcontractkit/wsrpc v0.8.3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 71959809eee..3b8c5987c00 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -11,7 +11,16 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ= @@ -21,6 +30,9 @@ cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v1.28.1 h1:XwPcZjgMCnU2tkwY10VleUjSAfpTj9RDn+kGrbYsi8o= cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= @@ -34,9 +46,12 @@ cloud.google.com/go/monitoring v1.21.1/go.mod h1:Rj++LKrlht9uBi8+Eb530dIrzG/cU/l cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.45.0 h1:5av0QcIVj77t+44mV4gffFC/LscFRUhto6UBMB5SimM= cloud.google.com/go/storage v1.45.0/go.mod h1:wpPblkIuMP5jCB/E48Pz9zIo2S/zD8g+ITmxKkPCITE= contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= @@ -160,15 +175,16 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/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= @@ -207,6 +223,7 @@ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= @@ -252,6 +269,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= @@ -343,7 +361,9 @@ github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -483,6 +503,7 @@ github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -507,7 +528,10 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -515,6 +539,7 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -544,9 +569,12 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= @@ -560,6 +588,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -567,6 +597,12 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= @@ -585,6 +621,7 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= @@ -781,6 +818,7 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E 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= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -800,6 +838,7 @@ github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZY github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -813,8 +852,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= -github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= @@ -833,6 +872,7 @@ github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/z github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 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= @@ -924,6 +964,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= @@ -967,6 +1009,7 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= @@ -982,6 +1025,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1080,36 +1124,42 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= -github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm3KUgyMDyK0v0aOtUk4= -github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= +github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc h1:2xPgOrBA7Zjjulcn31Bp6q0kOrONbEnII7iE/vSQVHk= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d h1:0tnjo1gpG16PHAouXamgDAAu6e7PWaM0Ppq6dMWnjx0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57 h1:1BMTG66HnCIz+KMBWGvyzELNM6VHGwv2WKFhN7H49Sg= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57/go.mod h1:QPiorgpbLv4+Jn4YO6xxU4ftTu4T3QN8HwX3ImP59DE= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db/go.mod h1:yjb9d4q7+m8aGbjfTbkNoNuA4PeSxcUszsSZHDrvS0E= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969 h1:M/SMFCY4URO0H1eB9r3pkRv0LS3Ofxk/GapSgGrLfFI= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969/go.mod h1:mGmRvlk54ufCufV4EBWizOGtXoXfePoFAuYEVC8EwdY= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtOAzKS4PrPIiJX65BGo1aYiYZxFVEW+jc= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 h1:lvn9Yxah+QD1/PcgijLO0dNRa28HuQWZl8Kkxh46KJc= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 h1:T0kbw07Vb6xUyA9MIJZfErMgWseWi1zf7cYvRpoq7ug= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13/go.mod h1:1CKUOzoK+Ga19WuhRH9pxZ+qUUnrlIx108VEA6qSzeQ= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= @@ -1118,10 +1168,12 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= -github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= +github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= @@ -1129,22 +1181,27 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= @@ -1250,6 +1307,7 @@ github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBi github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -1272,6 +1330,9 @@ go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYr go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= @@ -1282,6 +1343,7 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/detectors/gcp v1.31.0 h1:G1JQOreVrfhRkner+l4mrGxmfqYCAuy76asTDAo0xsA= @@ -1357,6 +1419,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -1411,6 +1474,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1419,9 +1483,12 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1440,6 +1507,7 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1448,11 +1516,21 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -1463,6 +1541,7 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= @@ -1471,6 +1550,13 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1480,7 +1566,9 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1523,17 +1611,29 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1563,6 +1663,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= @@ -1577,6 +1678,7 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= @@ -1624,14 +1726,31 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1655,8 +1774,19 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.202.0 h1:y1iuVHMqokQbimW79ZqPZWo4CiyFu6HcCYHwSNyzlfo= google.golang.org/api v0.202.0/go.mod h1:3Jjeq7M/SFblTNCp7ES2xhq+WvGL0KeXI0joHQBfwTQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -1665,6 +1795,8 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1684,12 +1816,33 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4= google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= @@ -1708,9 +1861,16 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/stats/opentelemetry v0.0.0-20241022174616-4bb0170ac65f h1:TsfHqsKI7qhOoYugDRyFDSKAuzegDVmkSCpjUyLkb+8= @@ -1723,6 +1883,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -1748,6 +1909,7 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= @@ -1778,6 +1940,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= diff --git a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go index f4e394b7da5..166022ac753 100644 --- a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go +++ b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go @@ -8,11 +8,9 @@ import ( "log" "os" "strings" - "time" "github.com/ethereum/go-ethereum/common" "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/durationpb" ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" @@ -34,126 +32,24 @@ type peer struct { var ( workflowDonPeers = []peer{ { - PeerID: "12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N", - Signer: "0x9639dCc7D0ca4468B5f684ef89F12F0B365c9F6d", - EncryptionPublicKey: "0xe7f44e3eedf3527199efec7334183b5384ba0e7c7c57b390b63a3de5a10cd53c", + PeerID: "12D3KooWQXfwA26jysiKKPXKuHcJtWTbGSwzoJxj4rYtEJyQTnFj", + Signer: "0xC44686106b85687F741e1d6182a5e2eD2211a115", + EncryptionPublicKey: "0x0f8b6629bc26321b39dfb7e2bc096584fe43dccfda54b67c24f53fd827efbc72", }, { - PeerID: "12D3KooWG1AyvwmCpZ93J8pBQUE1SuzrjDXnT4BeouncHR3jWLCG", - Signer: "0x8f0fAE64f5f75067833ed5deDC2804B62b21383d", - EncryptionPublicKey: "0x315c6097f89baef3c3ae1503b801aaabf411134ffec66bbe8d1d184540588728", + PeerID: "12D3KooWGCRg5wNKoRFUAypA68ZkwXz8dT5gyF3VdQpEH3FtLqHZ", + Signer: "0x0ee7C8Aa7F8cb5E08415C57B79d7d387F2665E8b", + EncryptionPublicKey: "0x4cb8a297d524469e63e8d8a15c7682891126987acaa39bc4f1db78c066f7af63", }, { - PeerID: "12D3KooWGeUKZBRMbx27FUTgBwZa9Ap9Ym92mywwpuqkEtz8XWyv", - Signer: "0xf09A863D920840c13277e76F43CFBdfB22b8FB7C", - EncryptionPublicKey: "0xa7a5e118213552a939f310e19167f49e9ad952cfe9d51eaae1ad37d92d9f0583", + PeerID: "12D3KooWHggbPfMcSSAwpBZHvwpo2UHzkf1ij3qjTnRiWQ7S5p4g", + Signer: "0xEd850731Be048afE986DaA90Bb482BC3b0f78aec", + EncryptionPublicKey: "0x7a9be509ace5f004fa397b7013893fed13a135dd273f7293dc3c7b6e57f1764e", }, { - PeerID: "12D3KooW9zYWQv3STmDeNDidyzxsJSTxoCTLicafgfeEz9nhwhC4", - Signer: "0x7eD90b519bC3054a575C464dBf39946b53Ff90EF", - EncryptionPublicKey: "0x75f75a86910eed0259e3107b3c368f72c0ad0301bac696fd340916e2437194c3", - }, - { - PeerID: "12D3KooWG1AeBnSJH2mdcDusXQVye2jqodZ6pftTH98HH6xvrE97", - Signer: "0x8F572978673d711b2F061EB7d514BD46EAD6668A", - EncryptionPublicKey: "0xd032f1e884a22fd05151f59565f05a4ccbf984afccbbee13469fc25947e69360", - }, - { - PeerID: "12D3KooWBf3PrkhNoPEmp7iV291YnPuuTsgEDHTscLajxoDvwHGA", - Signer: "0x21eF07Dfaf8f7C10CB0d53D18b641ee690541f9D", - EncryptionPublicKey: "0xed64ed4a2c2954f7390bfdf41a714934c0e55693ad1c0b91505d51f4eb9e4c06", - }, - { - PeerID: "12D3KooWP3FrMTFXXRU2tBC8aYvEBgUX6qhcH9q2JZCUi9Wvc2GX", - Signer: "0x7Fa21F6f716CFaF8f249564D72Ce727253186C89", - EncryptionPublicKey: "0xed64ed4a2c2954f7390bfdf41a714934c0e55693ad1c0b91505d51f4eb9e4c06", - }, - } - triggerDonPeers = []peer{ - { - PeerID: "12D3KooWBaiTbbRwwt2fbNifiL7Ew9tn3vds9AJE3Nf3eaVBX36m", - Signer: "0x9CcE7293a4Cc2621b61193135A95928735e4795F", - EncryptionPublicKey: "0xed64ed4a2c2954f7390bfdf41a714934c0e55693ad1c0b91505d51f4eb9e4c06", - }, - { - PeerID: "12D3KooWS7JSY9fzSfWgbCE1S3W2LNY6ZVpRuun74moVBkKj6utE", - Signer: "0x3c775F20bCB2108C1A818741Ce332Bb5fe0dB925", - EncryptionPublicKey: "0xed64ed4a2c2954f7390bfdf41a714934c0e55693ad1c0b91505d51f4eb9e4c06", - }, - { - PeerID: "12D3KooWMMTDXcWhpVnwrdAer1jnVARTmnr3RyT3v7Djg8ZuoBh9", - Signer: "0x50314239e2CF05555ceeD53E7F47eB2A8Eab0dbB", - EncryptionPublicKey: "0xce0e88d12d568653757f1db154f9c503db3d3d7b37cb03d84b61f39f09824cc0", - }, - { - PeerID: "12D3KooWGzVXsKxXsF4zLgxSDM8Gzx1ywq2pZef4PrHMKuVg4K3P", - Signer: "0xd76A4f98898c3b9A72b244476d7337b50D54BCd8", - EncryptionPublicKey: "0xce0e88d12d568653757f1db154f9c503db3d3d7b37cb03d84b61f39f09824cc0", - }, - { - PeerID: "12D3KooWSyjmmzjVtCzwN7bXzZQFmWiJRuVcKBerNjVgL7HdLJBW", - Signer: "0x656A873f6895b8a03Fb112dE927d43FA54B2c92A", - EncryptionPublicKey: "0x91f11910104ff55209d6d344a15eef6a222a54d4973aaebd301807444b555e3f", - }, - { - PeerID: "12D3KooWLGz9gzhrNsvyM6XnXS3JRkZoQdEzuAvysovnSChNK5ZK", - Signer: "0x5d1e87d87bF2e0cD4Ea64F381a2dbF45e5f0a553", - EncryptionPublicKey: "0x20ff771215e567cf7e9a1fea8f2d4df90adc8303794175f79893037ff8808b51", - }, - { - PeerID: "12D3KooWAvZnvknFAfSiUYjATyhzEJLTeKvAzpcLELHi4ogM3GET", - Signer: "0x91d9b0062265514f012Eb8fABA59372fD9520f56", - EncryptionPublicKey: "0x54176f154052068943569b676fa7eec7dc836e17bbe743ce56b1c7e205191d9c", - }, - } - targetDonPeers = []peer{ - { - PeerID: "12D3KooWJrthXtnPHw7xyHFAxo6NxifYTvc8igKYaA6wRRRqtsMb", - Signer: "0x3F82750353Ea7a051ec9bA011BC628284f9a5327", - EncryptionPublicKey: "0x1a746e0fcaf3e50db87bcc765fbbaee7d24a28166ea1461338a03fcbffb088cf", - }, - { - PeerID: "12D3KooWFQekP9sGex4XhqEJav5EScjTpDVtDqJFg1JvrePBCEGJ", - Signer: "0xc23545876A208AA0443B1b8d552c7be4FF4b53F0", - EncryptionPublicKey: "0x1a746e0fcaf3e50db87bcc765fbbaee7d24a28166ea1461338a03fcbffb088cf", - }, - { - PeerID: "12D3KooWFLEq4hYtdyKWwe47dXGEbSiHMZhmr5xLSJNhpfiEz8NF", - Signer: "0x82601Fa43d8B1dC1d4eB640451aC86a7CDA37011", - EncryptionPublicKey: "0x1a746e0fcaf3e50db87bcc765fbbaee7d24a28166ea1461338a03fcbffb088cf", - }, - { - PeerID: "12D3KooWN2hztiXNNS1jMQTTvvPRYcarK1C7T3Mdqk4x4gwyo5WS", - Signer: "0x1a684B3d8f917fe496b7B1A8b29EDDAED64F649f", - EncryptionPublicKey: "0x1a746e0fcaf3e50db87bcc765fbbaee7d24a28166ea1461338a03fcbffb088cf", - }, - } - - aptosTargetDonPeers = []peer{ - { - PeerID: "12D3KooWNBr1AD3vD3dzSLgg1tK56qyJoenDx7EYNnZpbr1g4jD6", - Signer: "a41f9a561ff2266d94240996a76f9c2b3b7d8184", - EncryptionPublicKey: "0xf28fcfaf2933289b3a98d387f6edf85853df32528c094dee9e737f4ca63e5a30", - }, - { - PeerID: "12D3KooWRRgWiZGw5GYsPa62CkwFNKJb5u4hWo4DinnvjG6GE6Nj", - Signer: "e4f3c7204776530fb7833db6f9dbfdb8bd0ec96892965324a71c20d6776f67f0", - EncryptionPublicKey: "0x49c837675372d8f430e69ccd91c43029600c2c6469a2f933c4a1c4bbbc974c6d", - }, - { - PeerID: "12D3KooWKwzgUHw5YbqUsYUVt3yiLSJcqc8ANofUtqHX6qTm7ox2", - Signer: "4071ea00e2e2c76b3406018ba9f66bf6b9aee3a6762e62ac823b1ee91ba7d7b0", - EncryptionPublicKey: "0x8fe005ef16d57091160c0b4373232e7389c321dff971fc0251a39e360d9ac34a", - }, - { - PeerID: "12D3KooWBRux5o2bw1j3SQwEHzCspjkt7Xe3Y3agRUuab2SUnExj", - Signer: "6f5180c7d276876dbe413bf9b0efff7301d1367f39f4bac64180090cab70989b", - EncryptionPublicKey: "0x90dd41db21351c06396761dd683a82c791cd71e536fce246e582a4ef058091ae", - }, - { - PeerID: "12D3KooWFqvDaMSDGa6eMSTF9en6G2c3ZbGLmaA5Xs3AgxVBPb8B", - Signer: "dbce9a6df8a04d54e52a109d01ee9b5d32873b1d2436cf7b7fae61fd6eca46f8", - EncryptionPublicKey: "0x87cf298dd236a307ea887cd5d81eb0b708e3dd48c984c0700bb26c072e427942", + PeerID: "12D3KooWC44picK3WvVkP1oufHYu1mB18xUg6mF2sNKM8Hc3EmdW", + Signer: "0xD3400B75f2016878dC2013ff2bC2Cf03bD5F19f5", + EncryptionPublicKey: "0x66dcec518809c1dd4ec5c094f651061b974d3cdbf5388cf4f47740c76fb58616", }, } @@ -304,7 +200,7 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { Version: "1.0.0", CapabilityType: uint8(0), // trigger } - sid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, streamsTrigger.LabelledName, streamsTrigger.Version) + _, err = reg.GetHashedCapabilityId(&bind.CallOpts{}, streamsTrigger.LabelledName, streamsTrigger.Version) if err != nil { panic(err) } @@ -334,7 +230,7 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { Version: "1.0.0", CapabilityType: uint8(3), // target } - wid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, writeChain.LabelledName, writeChain.Version) + _, err = reg.GetHashedCapabilityId(&bind.CallOpts{}, writeChain.LabelledName, writeChain.Version) if err != nil { log.Printf("failed to call GetHashedCapabilityId: %s", err) } @@ -344,7 +240,7 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { Version: "1.0.0", CapabilityType: uint8(3), // target } - awid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, aptosWriteChain.LabelledName, aptosWriteChain.Version) + _, err = reg.GetHashedCapabilityId(&bind.CallOpts{}, aptosWriteChain.LabelledName, aptosWriteChain.Version) if err != nil { log.Printf("failed to call GetHashedCapabilityId: %s", err) } @@ -402,36 +298,6 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { nodes = append(nodes, n) } - for _, triggerPeer := range triggerDonPeers { - n, innerErr := peerToNode(nopID, triggerPeer) - if innerErr != nil { - panic(innerErr) - } - - n.HashedCapabilityIds = [][32]byte{sid} - nodes = append(nodes, n) - } - - for _, targetPeer := range targetDonPeers { - n, innerErr := peerToNode(nopID, targetPeer) - if innerErr != nil { - panic(innerErr) - } - - n.HashedCapabilityIds = [][32]byte{wid} - nodes = append(nodes, n) - } - - for _, targetPeer := range aptosTargetDonPeers { - n, innerErr := peerToNode(nopID, targetPeer) - if innerErr != nil { - panic(innerErr) - } - - n.HashedCapabilityIds = [][32]byte{awid} - nodes = append(nodes, n) - } - tx, err = reg.AddNodes(env.Owner, nodes) if err != nil { log.Printf("failed to AddNodes: %s", err) @@ -476,95 +342,6 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { log.Printf("workflowDON: failed to AddDON: %s", err) } - // trigger DON - ps, err = peers(triggerDonPeers) - if err != nil { - panic(err) - } - - config := &capabilitiespb.CapabilityConfig{ - DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), - RemoteConfig: &capabilitiespb.CapabilityConfig_RemoteTriggerConfig{ - RemoteTriggerConfig: &capabilitiespb.RemoteTriggerConfig{ - RegistrationRefresh: durationpb.New(20 * time.Second), - RegistrationExpiry: durationpb.New(60 * time.Second), - // F + 1 - MinResponsesToAggregate: uint32(1) + 1, - }, - }, - } - configb, err := proto.Marshal(config) - if err != nil { - panic(err) - } - cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: sid, - Config: configb, - }, - } - _, err = reg.AddDON(env.Owner, ps, cfgs, true, false, 1) - if err != nil { - log.Printf("triggerDON: failed to AddDON: %s", err) - } - - // target DON - ps, err = peers(targetDonPeers) - if err != nil { - panic(err) - } - - targetCapabilityConfig := newCapabilityConfig() - targetCapabilityConfig.RemoteConfig = &capabilitiespb.CapabilityConfig_RemoteTargetConfig{ - RemoteTargetConfig: &capabilitiespb.RemoteTargetConfig{ - RequestHashExcludedAttributes: []string{"signed_report.Signatures"}, - }, - } - - remoteTargetConfigBytes, err := proto.Marshal(targetCapabilityConfig) - if err != nil { - panic(err) - } - - cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: wid, - Config: remoteTargetConfigBytes, - }, - } - _, err = reg.AddDON(env.Owner, ps, cfgs, true, false, 1) - if err != nil { - log.Printf("targetDON: failed to AddDON: %s", err) - } - - // Aptos target DON - ps, err = peers(aptosTargetDonPeers) - if err != nil { - panic(err) - } - - targetCapabilityConfig = newCapabilityConfig() - targetCapabilityConfig.RemoteConfig = &capabilitiespb.CapabilityConfig_RemoteTargetConfig{ - RemoteTargetConfig: &capabilitiespb.RemoteTargetConfig{ - RequestHashExcludedAttributes: []string{"signed_report.Signatures"}, - }, - } - - remoteTargetConfigBytes, err = proto.Marshal(targetCapabilityConfig) - if err != nil { - panic(err) - } - - cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: awid, - Config: remoteTargetConfigBytes, - }, - } - _, err = reg.AddDON(env.Owner, ps, cfgs, true, false, 1) - if err != nil { - log.Printf("targetDON: failed to AddDON: %s", err) - } } func deployCapabilitiesRegistry(env helpers.Environment) *kcr.CapabilitiesRegistry { diff --git a/core/scripts/keystone/src/88_gen_ocr3_config.go b/core/scripts/keystone/src/88_gen_ocr3_config.go index f4292e9a1d4..707616b833b 100644 --- a/core/scripts/keystone/src/88_gen_ocr3_config.go +++ b/core/scripts/keystone/src/88_gen_ocr3_config.go @@ -13,9 +13,8 @@ func mustReadConfig(fileName string) (output ksdeploy.TopLevelConfigSource) { func generateOCR3Config(nodeList string, configFile string, chainID int64, pubKeysPath string) ksdeploy.OCR2OracleConfig { topLevelCfg := mustReadConfig(configFile) cfg := topLevelCfg.OracleConfig - cfg.OCRSecrets = deployment.XXXGenerateTestOCRSecrets() nca := downloadNodePubKeys(nodeList, chainID, pubKeysPath) - c, err := ksdeploy.GenerateOCR3Config(cfg, nca) + c, err := ksdeploy.GenerateOCR3Config(cfg, nca, deployment.XXXGenerateTestOCRSecrets()) helpers.PanicErr(err) return c } diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index fef741c8c9b..29473c4d932 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -20,6 +20,7 @@ import ( "go.uber.org/multierr" "go.uber.org/zap/zapcore" + "github.com/smartcontractkit/chainlink-common/pkg/custmsg" "github.com/smartcontractkit/chainlink-common/pkg/loop" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -213,10 +214,16 @@ func NewApplication(opts ApplicationOpts) (Application, error) { opts.CapabilitiesRegistry = capabilities.NewRegistry(globalLogger) } - // TODO: wire this up to config so we only instantiate it - // if a workflow registry address is provided. - workflowRegistrySyncer := syncer.NewNullWorkflowRegistrySyncer() - srvcs = append(srvcs, workflowRegistrySyncer) + var gatewayConnectorWrapper *gatewayconnector.ServiceWrapper + if cfg.Capabilities().GatewayConnector().DonID() != "" { + globalLogger.Debugw("Creating GatewayConnector wrapper", "donID", cfg.Capabilities().GatewayConnector().DonID()) + gatewayConnectorWrapper = gatewayconnector.NewGatewayConnectorServiceWrapper( + cfg.Capabilities().GatewayConnector(), + keyStore.Eth(), + clockwork.NewRealClock(), + globalLogger) + srvcs = append(srvcs, gatewayConnectorWrapper) + } var externalPeerWrapper p2ptypes.PeerWrapper if cfg.Capabilities().Peering().Enabled() { @@ -262,32 +269,64 @@ func NewApplication(opts ApplicationOpts) (Application, error) { return nil, fmt.Errorf("could not configure syncer: %w", err) } + workflowDonNotifier := capabilities.NewDonNotifier() + wfLauncher := capabilities.NewLauncher( globalLogger, externalPeerWrapper, dispatcher, opts.CapabilitiesRegistry, + workflowDonNotifier, ) registrySyncer.AddLauncher(wfLauncher) srvcs = append(srvcs, wfLauncher, registrySyncer) + + if cfg.Capabilities().WorkflowRegistry().Address() != "" { + if gatewayConnectorWrapper == nil { + return nil, errors.New("unable to create workflow registry syncer without gateway connector") + } + + err = keyStore.Workflow().EnsureKey(context.Background()) + if err != nil { + return nil, fmt.Errorf("failed to ensure workflow key: %w", err) + } + + keys, err := keyStore.Workflow().GetAll() + if err != nil { + return nil, fmt.Errorf("failed to get all workflow keys: %w", err) + } + if len(keys) != 1 { + return nil, fmt.Errorf("expected 1 key, got %d", len(keys)) + } + + lggr := globalLogger.Named("WorkflowRegistrySyncer") + fetcher := syncer.NewFetcherService(lggr, gatewayConnectorWrapper) + + eventHandler := syncer.NewEventHandler(lggr, syncer.NewWorkflowRegistryDS(opts.DS, globalLogger), + fetcher.Fetch, workflowstore.NewDBStore(opts.DS, lggr, clockwork.NewRealClock()), opts.CapabilitiesRegistry, + custmsg.NewLabeler(), clockwork.NewRealClock(), keys[0]) + + loader := syncer.NewWorkflowRegistryContractLoader(lggr, cfg.Capabilities().WorkflowRegistry().Address(), func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { + return relayer.NewContractReader(ctx, bytes) + }, eventHandler) + + globalLogger.Debugw("Creating WorkflowRegistrySyncer") + wfSyncer := syncer.NewWorkflowRegistry(lggr, func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { + return relayer.NewContractReader(ctx, bytes) + }, cfg.Capabilities().WorkflowRegistry().Address(), + syncer.WorkflowEventPollerConfig{ + QueryCount: 100, + }, eventHandler, loader, workflowDonNotifier) + + srvcs = append(srvcs, fetcher, wfSyncer) + } } } else { globalLogger.Debug("External registry not configured, skipping registry syncer and starting with an empty registry") opts.CapabilitiesRegistry.SetLocalRegistry(&capabilities.TestMetadataRegistry{}) } - var gatewayConnectorWrapper *gatewayconnector.ServiceWrapper - if cfg.Capabilities().GatewayConnector().DonID() != "" { - globalLogger.Debugw("Creating GatewayConnector wrapper", "donID", cfg.Capabilities().GatewayConnector().DonID()) - gatewayConnectorWrapper = gatewayconnector.NewGatewayConnectorServiceWrapper( - cfg.Capabilities().GatewayConnector(), - keyStore.Eth(), - clockwork.NewRealClock(), - globalLogger) - srvcs = append(srvcs, gatewayConnectorWrapper) - } - // LOOPs can be created as options, in the case of LOOP relayers, or // as OCR2 job implementations, in the case of Median today. // We will have a non-nil registry here in LOOP relayers are being used, otherwise @@ -478,7 +517,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { delegates[job.Workflow] = workflows.NewDelegate( globalLogger, opts.CapabilitiesRegistry, - workflowRegistrySyncer, workflowORM, ) diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go index 8197b12ec7b..1be6e9337d1 100644 --- a/core/services/chainlink/relayer_chain_interoperators.go +++ b/core/services/chainlink/relayer_chain_interoperators.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/chains" @@ -154,7 +155,7 @@ func InitCosmos(ctx context.Context, factory RelayerFactory, config CosmosFactor // InitSolana is a option for instantiating Solana relayers func InitSolana(ctx context.Context, factory RelayerFactory, config SolanaFactoryConfig) CoreRelayerChainInitFunc { return func(op *CoreRelayerChainInteroperators) error { - solRelayers, err := factory.NewSolana(config.Keystore, config.TOMLConfigs) + solRelayers, err := factory.NewSolana(config) if err != nil { return fmt.Errorf("failed to setup Solana relayer: %w", err) } diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 32b64d402b1..a1571663d5a 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -107,9 +107,11 @@ func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (m type SolanaFactoryConfig struct { Keystore keystore.Solana solcfg.TOMLConfigs + DS sqlutil.DataSource } -func (r *RelayerFactory) NewSolana(ks keystore.Solana, chainCfgs solcfg.TOMLConfigs) (map[types.RelayID]loop.Relayer, error) { +func (r *RelayerFactory) NewSolana(config SolanaFactoryConfig) (map[types.RelayID]loop.Relayer, error) { + chainCfgs, ds, ks := config.TOMLConfigs, config.DS, config.Keystore solanaRelayers := make(map[types.RelayID]loop.Relayer) var ( solLggr = r.Logger.Named("Solana") @@ -162,6 +164,7 @@ func (r *RelayerFactory) NewSolana(ks keystore.Solana, chainCfgs solcfg.TOMLConf opts := solana.ChainOpts{ Logger: lggr, KeyStore: signer, + DS: ds, } chain, err := solana.NewChain(chainCfg, opts) diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go index 61b2d53f2d5..04ab747c9ab 100644 --- a/core/services/feeds/service.go +++ b/core/services/feeds/service.go @@ -19,9 +19,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ccip "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" + "github.com/smartcontractkit/chainlink/v2/core/services/streams" "github.com/smartcontractkit/chainlink/v2/plugins" pb "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -126,6 +128,7 @@ type service struct { p2pKeyStore keystore.P2P ocr1KeyStore keystore.OCR ocr2KeyStore keystore.OCR2 + workflowKeyStore keystore.Workflow jobSpawner job.Spawner gCfg GeneralConfig featCfg FeatureConfig @@ -168,6 +171,7 @@ func NewService( csaKeyStore: keyStore.CSA(), ocr1KeyStore: keyStore.OCR(), ocr2KeyStore: keyStore.OCR2(), + workflowKeyStore: keyStore.Workflow(), gCfg: gCfg, featCfg: fCfg, insecureCfg: insecureCfg, @@ -275,9 +279,11 @@ func (s *service) SyncNodeInfo(ctx context.Context, id int64) error { cfgMsgs = append(cfgMsgs, cfgMsg) } + workflowKey := s.getWorkflowPublicKey() if _, err = fmsClient.UpdateNode(ctx, &pb.UpdateNodeRequest{ Version: s.version, ChainConfigs: cfgMsgs, + WorkflowKey: &workflowKey, }); err != nil { return err } @@ -510,6 +516,33 @@ func (s *service) DeleteJob(ctx context.Context, args *DeleteJobArgs) (int64, er logger.Errorw("Failed to push metrics for job proposal deletion", "err", err) } + // auto-cancellation for Workflow specs + if !proposal.ExternalJobID.Valid { + logger.Infow("ExternalJobID is null", "id", proposal.ID, "name", proposal.Name) + return proposal.ID, nil + } + job, err := s.jobORM.FindJobByExternalJobID(ctx, proposal.ExternalJobID.UUID) + if err != nil { + // NOTE: at this stage, we don't know if this job is of Workflow type + // so we don't want to return an error + logger.Infow("FindJobByExternalJobID failed", "id", proposal.ID, "externalJobID", proposal.ExternalJobID.UUID, "name", proposal.Name) + return proposal.ID, nil + } + if job.WorkflowSpecID != nil { // this is a Workflow job + jobSpecID := int64(*job.WorkflowSpecID) + jpSpec, err2 := s.orm.GetApprovedSpec(ctx, proposal.ID) + if err2 != nil { + logger.Errorw("GetApprovedSpec failed - no approved specs to cancel?", "id", proposal.ID, "err", err2, "name", job.Name) + // return success if there are no approved specs to cancel + return proposal.ID, nil + } + if err := s.CancelSpec(ctx, jpSpec.ID); err != nil { + logger.Errorw("Failed to auto-cancel workflow spec", "jobProposalID", proposal.ID, "jobProposalSpecID", jpSpec.ID, "jobSpecID", jobSpecID, "err", err, "name", job.Name) + return 0, fmt.Errorf("failed to auto-cancel workflow spec (job proposal spec ID: %d): %w", jpSpec.ID, err) + } + logger.Infow("Successfully auto-cancelled a workflow spec", "jobProposalID", proposal.ID, "jobProposalSpecID", jpSpec.ID, "jobSpecID", jobSpecID, "name", job.Name) + } + return proposal.ID, nil } @@ -859,6 +892,13 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { if txerr != nil && !errors.Is(txerr, sql.ErrNoRows) { return fmt.Errorf("failed while checking for existing ccip job: %w", txerr) } + case job.Stream: + existingJobID, txerr = tx.jobORM.FindJobIDByStreamID(ctx, *j.StreamID) + // Return an error if the repository errors. If there is a not found + // error we want to continue with approving the job. + if txerr != nil && !errors.Is(txerr, sql.ErrNoRows) { + return fmt.Errorf("failed while checking for existing stream job: %w", txerr) + } default: return errors.Errorf("unsupported job type when approving job proposal specs: %s", j.Type) } @@ -1143,6 +1183,20 @@ func (s *service) getCSAPrivateKey() (privkey []byte, err error) { return keys[0].Raw(), nil } +// getWorkflowPublicKey retrieves the server's Workflow public key. +// Since there will be at most one key, it returns the first key found. +// If an error occurs or no keys are found, it returns blank. +func (s *service) getWorkflowPublicKey() string { + keys, err := s.workflowKeyStore.GetAll() + if err != nil { + return "" + } + if len(keys) < 1 { + return "" + } + return keys[0].PublicKeyString() +} + // observeJobProposalCounts is a helper method that queries the repository for the count of // job proposals by status and then updates prometheus gauges. func (s *service) observeJobProposalCounts(ctx context.Context) error { @@ -1249,6 +1303,8 @@ func (s *service) generateJob(ctx context.Context, spec string) (*job.Job, error js, err = workflows.ValidatedWorkflowJobSpec(ctx, spec) case job.CCIP: js, err = ccip.ValidatedCCIPSpec(spec) + case job.Stream: + js, err = streams.ValidatedStreamSpec(spec) default: return nil, errors.Errorf("unknown job type: %s", jobType) } diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go index 5369d645c4e..d449d585401 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -21,6 +21,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" proto "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" evmbig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -39,6 +40,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" ksmocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/versioning" @@ -135,6 +137,41 @@ answer1 [type=median index=0]; [pluginConfig.juelsPerFeeCoinCache] updateInterval = "1m" ` + +const StreamTestSpecTemplate = ` +name = '%s' +type = 'stream' +schemaVersion = 1 +externalJobID = '%s' +streamID = %d +observationSource = """ +ds1_payload [type=bridge name=\"bridge-ncfx\" timeout=\"50s\" requestData=\"{\\\"data\\\":{\\\"endpoint\\\":\\\"cryptolwba\\\",\\\"from\\\":\\\"SEI\\\",\\\"to\\\":\\\"USD\\\"}}\"]; +ds1_benchmark [type=jsonparse path=\"data,mid\"]; +ds1_bid [type=jsonparse path=\"data,bid\"]; +ds1_ask [type=jsonparse path=\"data,ask\"]; +ds2_payload [type=bridge name=\"bridge-tiingo\" timeout=\"50s\" requestData=\"{\\\"data\\\":{\\\"endpoint\\\":\\\"cryptolwba\\\",\\\"from\\\":\\\"SEI\\\",\\\"to\\\":\\\"USD\\\"}}\"]; +ds2_benchmark [type=jsonparse path=\"data,mid\"]; +ds2_bid [type=jsonparse path=\"data,bid\"]; +ds2_ask [type=jsonparse path=\"data,ask\"]; +ds3_payload [type=bridge name=\"bridge-gsr\" timeout=\"50s\" requestData=\"{\\\"data\\\":{\\\"endpoint\\\":\\\"cryptolwba\\\",\\\"from\\\":\\\"SEI\\\",\\\"to\\\":\\\"USD\\\"}}\"]; +ds3_benchmark [type=jsonparse path=\"data,mid\"]; +ds3_bid [type=jsonparse path=\"data,bid\"]; +ds3_ask [type=jsonparse path=\"data,ask\"]; +ds1_payload -> ds1_benchmark -> benchmark_price; +ds2_payload -> ds2_benchmark -> benchmark_price; +ds3_payload -> ds3_benchmark -> benchmark_price; +benchmark_price [type=median allowedFaults=2 index=0]; +ds1_payload -> ds1_bid -> bid_price; +ds2_payload -> ds2_bid -> bid_price; +ds3_payload -> ds3_bid -> bid_price; +bid_price [type=median allowedFaults=2 index=1]; +ds1_payload -> ds1_ask -> ask_price; +ds2_payload -> ds2_ask -> ask_price; +ds3_payload -> ds3_ask -> ask_price; +ask_price [type=median allowedFaults=2 index=2]; +""" +` + const BootstrapTestSpecTemplate = ` type = "bootstrap" schemaVersion = 1 @@ -147,16 +184,17 @@ chainID = 1337 type TestService struct { feeds.Service - orm *mocks.ORM - jobORM *jobmocks.ORM - connMgr *mocks.ConnectionsManager - spawner *jobmocks.Spawner - fmsClient *mocks.FeedsManagerClient - csaKeystore *ksmocks.CSA - p2pKeystore *ksmocks.P2P - ocr1Keystore *ksmocks.OCR - ocr2Keystore *ksmocks.OCR2 - legacyChains legacyevm.LegacyChainContainer + orm *mocks.ORM + jobORM *jobmocks.ORM + connMgr *mocks.ConnectionsManager + spawner *jobmocks.Spawner + fmsClient *mocks.FeedsManagerClient + csaKeystore *ksmocks.CSA + p2pKeystore *ksmocks.P2P + ocr1Keystore *ksmocks.OCR + ocr2Keystore *ksmocks.OCR2 + workflowKeystore *ksmocks.Workflow + legacyChains legacyevm.LegacyChainContainer } func setupTestService(t *testing.T) *TestService { @@ -169,15 +207,16 @@ func setupTestServiceCfg(t *testing.T, overrideCfg func(c *chainlink.Config, s * t.Helper() var ( - orm = mocks.NewORM(t) - jobORM = jobmocks.NewORM(t) - connMgr = mocks.NewConnectionsManager(t) - spawner = jobmocks.NewSpawner(t) - fmsClient = mocks.NewFeedsManagerClient(t) - csaKeystore = ksmocks.NewCSA(t) - p2pKeystore = ksmocks.NewP2P(t) - ocr1Keystore = ksmocks.NewOCR(t) - ocr2Keystore = ksmocks.NewOCR2(t) + orm = mocks.NewORM(t) + jobORM = jobmocks.NewORM(t) + connMgr = mocks.NewConnectionsManager(t) + spawner = jobmocks.NewSpawner(t) + fmsClient = mocks.NewFeedsManagerClient(t) + csaKeystore = ksmocks.NewCSA(t) + p2pKeystore = ksmocks.NewP2P(t) + ocr1Keystore = ksmocks.NewOCR(t) + ocr2Keystore = ksmocks.NewOCR2(t) + workflowKeystore = ksmocks.NewWorkflow(t) ) lggr := logger.TestLogger(t) @@ -193,21 +232,23 @@ func setupTestServiceCfg(t *testing.T, overrideCfg func(c *chainlink.Config, s * keyStore.On("P2P").Return(p2pKeystore) keyStore.On("OCR").Return(ocr1Keystore) keyStore.On("OCR2").Return(ocr2Keystore) + keyStore.On("Workflow").Return(workflowKeystore) svc := feeds.NewService(orm, jobORM, db, spawner, keyStore, gcfg, gcfg.Feature(), gcfg.Insecure(), gcfg.JobPipeline(), gcfg.OCR(), gcfg.OCR2(), legacyChains, lggr, "1.0.0", nil) svc.SetConnectionsManager(connMgr) return &TestService{ - Service: svc, - orm: orm, - jobORM: jobORM, - connMgr: connMgr, - spawner: spawner, - fmsClient: fmsClient, - csaKeystore: csaKeystore, - p2pKeystore: p2pKeystore, - ocr1Keystore: ocr1Keystore, - ocr2Keystore: ocr2Keystore, - legacyChains: legacyChains, + Service: svc, + orm: orm, + jobORM: jobORM, + connMgr: connMgr, + spawner: spawner, + fmsClient: fmsClient, + csaKeystore: csaKeystore, + p2pKeystore: p2pKeystore, + ocr1Keystore: ocr1Keystore, + ocr2Keystore: ocr2Keystore, + workflowKeystore: workflowKeystore, + legacyChains: legacyChains, } } @@ -577,10 +618,15 @@ func Test_Service_CreateChainConfig(t *testing.T) { svc = setupTestService(t) ) + workflowKey, err := workflowkey.New() + require.NoError(t, err) + svc.workflowKeystore.On("GetAll").Return([]workflowkey.Key{workflowKey}, nil) + svc.orm.On("CreateChainConfig", mock.Anything, cfg).Return(int64(1), nil) svc.orm.On("GetManager", mock.Anything, mgr.ID).Return(&mgr, nil) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) + wkID := workflowKey.ID() svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{ @@ -597,6 +643,7 @@ func Test_Service_CreateChainConfig(t *testing.T) { Ocr2Config: &proto.OCR2Config{Enabled: false}, }, }, + WorkflowKey: &wkID, }).Return(&proto.UpdateNodeResponse{}, nil) actual, err := svc.CreateChainConfig(testutils.Context(t), cfg) @@ -641,14 +688,20 @@ func Test_Service_DeleteChainConfig(t *testing.T) { svc = setupTestService(t) ) + workflowKey, err := workflowkey.New() + require.NoError(t, err) + svc.workflowKeystore.On("GetAll").Return([]workflowkey.Key{workflowKey}, nil) + svc.orm.On("GetChainConfig", mock.Anything, cfg.ID).Return(&cfg, nil) svc.orm.On("DeleteChainConfig", mock.Anything, cfg.ID).Return(cfg.ID, nil) svc.orm.On("GetManager", mock.Anything, mgr.ID).Return(&mgr, nil) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{}, nil) + wkID := workflowKey.ID() svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{}, + WorkflowKey: &wkID, }).Return(&proto.UpdateNodeResponse{}, nil) actual, err := svc.DeleteChainConfig(testutils.Context(t), cfg.ID) @@ -726,10 +779,15 @@ func Test_Service_UpdateChainConfig(t *testing.T) { svc = setupTestService(t) ) + workflowKey, err := workflowkey.New() + require.NoError(t, err) + svc.workflowKeystore.On("GetAll").Return([]workflowkey.Key{workflowKey}, nil) + svc.orm.On("UpdateChainConfig", mock.Anything, cfg).Return(int64(1), nil) svc.orm.On("GetChainConfig", mock.Anything, cfg.ID).Return(&cfg, nil) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) + wkID := workflowKey.ID() svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{ @@ -746,6 +804,7 @@ func Test_Service_UpdateChainConfig(t *testing.T) { Ocr2Config: &proto.OCR2Config{Enabled: false}, }, }, + WorkflowKey: &wkID, }).Return(&proto.UpdateNodeResponse{}, nil) actual, err := svc.UpdateChainConfig(testutils.Context(t), cfg) @@ -1270,12 +1329,25 @@ func Test_Service_DeleteJob(t *testing.T) { } approved = feeds.JobProposal{ - ID: 1, + ID: 321, FeedsManagerID: 1, RemoteUUID: remoteUUID, + ExternalJobID: uuid.NullUUID{UUID: uuid.New(), Valid: true}, Status: feeds.JobProposalStatusApproved, } + wfSpecID = int32(4321) + workflowJob = job.Job{ + ID: 1, + WorkflowSpecID: &wfSpecID, + } + jobProposalSpec = &feeds.JobProposalSpec{ + ID: 20, + Status: feeds.SpecStatusApproved, + JobProposalID: approved.ID, + Version: 1, + } + httpTimeout = *commonconfig.MustNewDuration(1 * time.Second) ) @@ -1292,6 +1364,7 @@ func Test_Service_DeleteJob(t *testing.T) { svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID).Return(&approved, nil) svc.orm.On("DeleteProposal", mock.Anything, approved.ID).Return(nil) svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, approved.ExternalJobID.UUID).Return(job.Job{}, sql.ErrNoRows) }, args: args, wantID: approved.ID, @@ -1335,6 +1408,38 @@ func Test_Service_DeleteJob(t *testing.T) { args: args, wantErr: "DeleteProposal failed", }, + { + name: "Delete workflow-spec with auto-cancellation", + before: func(svc *TestService) { + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID).Return(&approved, nil) + svc.orm.On("DeleteProposal", mock.Anything, approved.ID).Return(nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, approved.ExternalJobID.UUID).Return(workflowJob, nil) + svc.orm.On("GetApprovedSpec", mock.Anything, approved.ID).Return(jobProposalSpec, nil) + + // mocks for CancelSpec() + svc.orm.On("GetSpec", mock.Anything, jobProposalSpec.ID).Return(jobProposalSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, approved.ID).Return(&approved, nil) + svc.connMgr.On("GetClient", mock.Anything).Return(svc.fmsClient, nil) + + svc.orm.On("CancelSpec", mock.Anything, jobProposalSpec.ID).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, approved.ExternalJobID.UUID).Return(workflowJob, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, workflowJob.ID).Return(nil) + + svc.fmsClient.On("CancelledJob", + mock.MatchedBy(func(ctx context.Context) bool { return true }), + &proto.CancelledJobRequest{ + Uuid: approved.RemoteUUID.String(), + Version: int64(jobProposalSpec.Version), + }, + ).Return(&proto.CancelledJobResponse{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + }, + args: args, + wantID: approved.ID, + }, } for _, tc := range testCases { @@ -1626,6 +1731,9 @@ func Test_Service_SyncNodeInfo(t *testing.T) { ocrKey, err := ocrkey.NewV2() require.NoError(t, err) + workflowKey, err := workflowkey.New() + require.NoError(t, err) + var ( multiaddr = "/dns4/chain.link/tcp/1234/p2p/16Uiu2HAm58SP7UL8zsnpeuwHfytLocaqgnyaYKP8wu7qRdrixLju" mgr = &feeds.FeedsManager{ID: 1} @@ -1673,6 +1781,8 @@ func Test_Service_SyncNodeInfo(t *testing.T) { svc.p2pKeystore.On("Get", p2pKey.PeerID()).Return(p2pKey, nil) svc.ocr1Keystore.On("Get", ocrKey.GetID()).Return(ocrKey, nil) + svc.workflowKeystore.On("GetAll").Return([]workflowkey.Key{workflowKey}, nil) + wkID := workflowKey.ID() svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{ @@ -1713,6 +1823,7 @@ func Test_Service_SyncNodeInfo(t *testing.T) { }, }, }, + WorkflowKey: &wkID, }).Return(&proto.UpdateNodeResponse{}, nil) err = svc.SyncNodeInfo(testutils.Context(t), mgr.ID) @@ -3269,6 +3380,514 @@ updateInterval = "20m" } } +func Test_Service_ApproveSpec_Stream(t *testing.T) { + externalJobID := uuid.New() + streamName := "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" + streamID := uint32(1009001032) + + var ( + ctx = testutils.Context(t) + + jp = &feeds.JobProposal{ + ID: 1, + FeedsManagerID: 100, + } + spec = &feeds.JobProposalSpec{ + ID: 20, + Status: feeds.SpecStatusPending, + JobProposalID: jp.ID, + Version: 1, + Definition: fmt.Sprintf(StreamTestSpecTemplate, streamName, externalJobID.String(), streamID), + } + rejectedSpec = &feeds.JobProposalSpec{ + ID: 20, + Status: feeds.SpecStatusRejected, + JobProposalID: jp.ID, + Version: 1, + Definition: fmt.Sprintf(StreamTestSpecTemplate, streamName, externalJobID.String(), streamID), + } + cancelledSpec = &feeds.JobProposalSpec{ + ID: 20, + Status: feeds.SpecStatusCancelled, + JobProposalID: jp.ID, + Version: 1, + Definition: fmt.Sprintf(StreamTestSpecTemplate, streamName, externalJobID.String(), streamID), + } + j = job.Job{ + ID: 1, + ExternalJobID: externalJobID, + } + ) + + testCases := []struct { + name string + httpTimeout *commonconfig.Duration + before func(svc *TestService) + id int64 + force bool + wantErr string + }{ + { + name: "pending job success", + httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), + before: func(svc *TestService) { + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) + svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(int32(0), sql.ErrNoRows) + + svc.spawner. + On("CreateJob", + mock.Anything, + mock.Anything, + mock.MatchedBy(func(j *job.Job) bool { + return j.Name.String == streamName + }), + ). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). + Return(nil) + svc.orm.On("ApproveSpec", + mock.Anything, + spec.ID, + externalJobID, + ).Return(nil) + svc.fmsClient.On("ApprovedJob", + mock.MatchedBy(func(ctx context.Context) bool { return true }), + &proto.ApprovedJobRequest{ + Uuid: jp.RemoteUUID.String(), + Version: int64(spec.Version), + }, + ).Return(&proto.ApprovedJobResponse{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + }, + id: spec.ID, + force: false, + }, + { + name: "cancelled spec success when it is the latest spec", + httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), + before: func(svc *TestService) { + svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(cancelledSpec, nil) + svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) + + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(int32(0), sql.ErrNoRows) + + svc.spawner. + On("CreateJob", + mock.Anything, + mock.Anything, + mock.MatchedBy(func(j *job.Job) bool { + return j.Name.String == streamName + }), + ). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). + Return(nil) + svc.orm.On("ApproveSpec", + mock.Anything, + cancelledSpec.ID, + externalJobID, + ).Return(nil) + svc.fmsClient.On("ApprovedJob", + mock.MatchedBy(func(ctx context.Context) bool { return true }), + &proto.ApprovedJobRequest{ + Uuid: jp.RemoteUUID.String(), + Version: int64(spec.Version), + }, + ).Return(&proto.ApprovedJobResponse{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + }, + id: cancelledSpec.ID, + force: false, + }, + { + name: "cancelled spec failed not latest spec", + before: func(svc *TestService) { + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + ID: 21, + Status: feeds.SpecStatusPending, + JobProposalID: jp.ID, + Version: 2, + Definition: StreamTestSpecTemplate, + }, nil) + }, + id: cancelledSpec.ID, + force: false, + wantErr: "cannot approve a cancelled spec", + }, + { + name: "rejected spec failed cannot be approved", + before: func(svc *TestService) { + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + }, + id: rejectedSpec.ID, + force: false, + wantErr: "cannot approve a rejected spec", + }, + { + name: "already existing job replacement error", + httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), + before: func(svc *TestService) { + svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(j.ID, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + }, + id: spec.ID, + force: false, + wantErr: "could not approve job proposal: a job for this contract address already exists - please use the 'force' option to replace it", + }, + { + name: "already existing self managed job replacement success if forced without feedID", + httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), + before: func(svc *TestService) { + svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) + + svc.spawner. + On("CreateJob", + mock.Anything, + mock.Anything, + mock.MatchedBy(func(j *job.Job) bool { + return j.Name.String == streamName + }), + ). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). + Return(nil) + svc.orm.On("ApproveSpec", + mock.Anything, + spec.ID, + externalJobID, + ).Return(nil) + svc.fmsClient.On("ApprovedJob", + mock.MatchedBy(func(ctx context.Context) bool { return true }), + &proto.ApprovedJobRequest{ + Uuid: jp.RemoteUUID.String(), + Version: int64(spec.Version), + }, + ).Return(&proto.ApprovedJobResponse{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + }, + id: spec.ID, + force: true, + }, + { + name: "already existing self managed job replacement success if forced with feedID", + httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), + before: func(svc *TestService) { + svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(&feeds.JobProposalSpec{ + ID: 20, + Status: feeds.SpecStatusPending, + JobProposalID: jp.ID, + Version: 1, + Definition: fmt.Sprintf(StreamTestSpecTemplate, streamName, externalJobID.String(), streamID), + }, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) + + svc.spawner. + On("CreateJob", + mock.Anything, + mock.Anything, + mock.MatchedBy(func(j *job.Job) bool { + return j.Name.String == streamName + }), + ). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). + Return(nil) + svc.orm.On("ApproveSpec", + mock.Anything, + spec.ID, + externalJobID, + ).Return(nil) + svc.fmsClient.On("ApprovedJob", + mock.MatchedBy(func(ctx context.Context) bool { return true }), + &proto.ApprovedJobRequest{ + Uuid: jp.RemoteUUID.String(), + Version: int64(spec.Version), + }, + ).Return(&proto.ApprovedJobResponse{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + }, + id: spec.ID, + force: true, + }, + { + name: "already existing FMS managed job replacement success if forced", + httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), + before: func(svc *TestService) { + svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(&feeds.JobProposalSpec{ID: 100}, nil) + svc.orm.EXPECT().CancelSpec(mock.Anything, int64(100)).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) + + svc.spawner. + On("CreateJob", + mock.Anything, + mock.Anything, + mock.MatchedBy(func(j *job.Job) bool { + return j.Name.String == streamName + }), + ). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). + Return(nil) + svc.orm.On("ApproveSpec", + mock.Anything, + spec.ID, + externalJobID, + ).Return(nil) + svc.fmsClient.On("ApprovedJob", + mock.MatchedBy(func(ctx context.Context) bool { return true }), + &proto.ApprovedJobRequest{ + Uuid: jp.RemoteUUID.String(), + Version: int64(spec.Version), + }, + ).Return(&proto.ApprovedJobResponse{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + }, + id: spec.ID, + force: true, + }, + { + name: "spec does not exist", + before: func(svc *TestService) { + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(nil, errors.New("Not Found")) + }, + id: spec.ID, + force: false, + wantErr: "orm: job proposal spec: Not Found", + }, + { + name: "cannot approve an approved spec", + before: func(svc *TestService) { + aspec := &feeds.JobProposalSpec{ + ID: spec.ID, + JobProposalID: jp.ID, + Status: feeds.SpecStatusApproved, + } + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(aspec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + }, + id: spec.ID, + force: false, + wantErr: "cannot approve an approved spec", + }, + { + name: "cannot approved a rejected spec", + before: func(svc *TestService) { + rspec := &feeds.JobProposalSpec{ + ID: spec.ID, + JobProposalID: jp.ID, + Status: feeds.SpecStatusRejected, + } + svc.orm.On("GetSpec", mock.Anything, rspec.ID, mock.Anything).Return(rspec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + }, + id: spec.ID, + force: false, + wantErr: "cannot approve a rejected spec", + }, + { + name: "job proposal does not exist", + before: func(svc *TestService) { + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(nil, errors.New("Not Found")) + }, + id: spec.ID, + wantErr: "orm: job proposal: Not Found", + }, + { + name: "bridges do not exist", + httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), + before: func(svc *TestService) { + svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(errors.New("bridges do not exist")) + }, + id: spec.ID, + wantErr: "failed to approve job spec due to bridge check: bridges do not exist", + }, + { + name: "rpc client not connected", + before: func(svc *TestService) { + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(nil, errors.New("Not Connected")) + }, + id: spec.ID, + force: false, + wantErr: "fms rpc client: Not Connected", + }, + { + name: "create job error", + httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), + before: func(svc *TestService) { + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) + svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) + + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(int32(0), sql.ErrNoRows) + + svc.spawner. + On("CreateJob", + mock.Anything, + mock.Anything, + mock.MatchedBy(func(j *job.Job) bool { + return j.Name.String == streamName + }), + ). + Return(errors.New("could not save")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + }, + id: spec.ID, + force: false, + wantErr: "could not approve job proposal: could not save", + }, + { + name: "approve spec orm error", + httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), + before: func(svc *TestService) { + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) + svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) + + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(int32(0), sql.ErrNoRows) + + svc.spawner. + On("CreateJob", + mock.Anything, + mock.Anything, + mock.MatchedBy(func(j *job.Job) bool { + return j.Name.String == streamName + }), + ). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). + Return(nil) + svc.orm.On("ApproveSpec", + mock.Anything, + spec.ID, + externalJobID, + ).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + }, + id: spec.ID, + force: false, + wantErr: "could not approve job proposal: failure", + }, + { + name: "fms call error", + httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), + before: func(svc *TestService) { + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) + svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) + + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(int32(0), sql.ErrNoRows) + + svc.spawner. + On("CreateJob", + mock.Anything, + mock.Anything, + mock.MatchedBy(func(j *job.Job) bool { + return j.Name.String == streamName + }), + ). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). + Return(nil) + svc.orm.On("ApproveSpec", + mock.Anything, + spec.ID, + externalJobID, + ).Return(nil) + svc.fmsClient.On("ApprovedJob", + mock.MatchedBy(func(ctx context.Context) bool { return true }), + &proto.ApprovedJobRequest{ + Uuid: jp.RemoteUUID.String(), + Version: int64(spec.Version), + }, + ).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) + }, + id: spec.ID, + force: false, + wantErr: "could not approve job proposal: failure", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + svc := setupTestServiceCfg(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.OCR2.Enabled = testutils.Ptr(true) + if tc.httpTimeout != nil { + c.JobPipeline.HTTPRequest.DefaultTimeout = tc.httpTimeout + } + }) + + if tc.before != nil { + tc.before(svc) + } + + err := svc.ApproveSpec(ctx, tc.id, tc.force) + + if tc.wantErr != "" { + require.Error(t, err) + assert.EqualError(t, err, tc.wantErr) + } else { + require.NoError(t, err) + } + }) + } +} + func Test_Service_ApproveSpec_Bootstrap(t *testing.T) { address := "0x613a38AC1659769640aaE063C651F48E0250454C" feedIDHex := "0x0000000000000000000000000000000000000000000000000000000000000001" diff --git a/core/services/gateway/connector/connector.go b/core/services/gateway/connector/connector.go index 18d34007c56..a8d356478e9 100644 --- a/core/services/gateway/connector/connector.go +++ b/core/services/gateway/connector/connector.go @@ -23,7 +23,7 @@ import ( // GatewayConnector is a component run by Nodes to connect to a set of Gateways. type GatewayConnector interface { - job.ServiceCtx + services.Service network.ConnectionInitiator AddHandler(methods []string, handler GatewayConnectorHandler) error diff --git a/core/services/gateway/connector/mocks/gateway_connector.go b/core/services/gateway/connector/mocks/gateway_connector.go index f9951af98e9..183fc949cd5 100644 --- a/core/services/gateway/connector/mocks/gateway_connector.go +++ b/core/services/gateway/connector/mocks/gateway_connector.go @@ -269,6 +269,98 @@ func (_c *GatewayConnector_GatewayIDs_Call) RunAndReturn(run func() []string) *G return _c } +// HealthReport provides a mock function with given fields: +func (_m *GatewayConnector) HealthReport() map[string]error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for HealthReport") + } + + var r0 map[string]error + if rf, ok := ret.Get(0).(func() map[string]error); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]error) + } + } + + return r0 +} + +// GatewayConnector_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' +type GatewayConnector_HealthReport_Call struct { + *mock.Call +} + +// HealthReport is a helper method to define mock.On call +func (_e *GatewayConnector_Expecter) HealthReport() *GatewayConnector_HealthReport_Call { + return &GatewayConnector_HealthReport_Call{Call: _e.mock.On("HealthReport")} +} + +func (_c *GatewayConnector_HealthReport_Call) Run(run func()) *GatewayConnector_HealthReport_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GatewayConnector_HealthReport_Call) Return(_a0 map[string]error) *GatewayConnector_HealthReport_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GatewayConnector_HealthReport_Call) RunAndReturn(run func() map[string]error) *GatewayConnector_HealthReport_Call { + _c.Call.Return(run) + return _c +} + +// Name provides a mock function with given fields: +func (_m *GatewayConnector) Name() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Name") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// GatewayConnector_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' +type GatewayConnector_Name_Call struct { + *mock.Call +} + +// Name is a helper method to define mock.On call +func (_e *GatewayConnector_Expecter) Name() *GatewayConnector_Name_Call { + return &GatewayConnector_Name_Call{Call: _e.mock.On("Name")} +} + +func (_c *GatewayConnector_Name_Call) Run(run func()) *GatewayConnector_Name_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GatewayConnector_Name_Call) Return(_a0 string) *GatewayConnector_Name_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GatewayConnector_Name_Call) RunAndReturn(run func() string) *GatewayConnector_Name_Call { + _c.Call.Return(run) + return _c +} + // NewAuthHeader provides a mock function with given fields: _a0 func (_m *GatewayConnector) NewAuthHeader(_a0 *url.URL) ([]byte, error) { ret := _m.Called(_a0) @@ -327,6 +419,51 @@ func (_c *GatewayConnector_NewAuthHeader_Call) RunAndReturn(run func(*url.URL) ( return _c } +// Ready provides a mock function with given fields: +func (_m *GatewayConnector) Ready() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Ready") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GatewayConnector_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' +type GatewayConnector_Ready_Call struct { + *mock.Call +} + +// Ready is a helper method to define mock.On call +func (_e *GatewayConnector_Expecter) Ready() *GatewayConnector_Ready_Call { + return &GatewayConnector_Ready_Call{Call: _e.mock.On("Ready")} +} + +func (_c *GatewayConnector_Ready_Call) Run(run func()) *GatewayConnector_Ready_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GatewayConnector_Ready_Call) Return(_a0 error) *GatewayConnector_Ready_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GatewayConnector_Ready_Call) RunAndReturn(run func() error) *GatewayConnector_Ready_Call { + _c.Call.Return(run) + return _c +} + // SendToGateway provides a mock function with given fields: ctx, gatewayId, msg func (_m *GatewayConnector) SendToGateway(ctx context.Context, gatewayId string, msg *api.Message) error { ret := _m.Called(ctx, gatewayId, msg) diff --git a/core/services/gateway/handlers/capabilities/handler.go b/core/services/gateway/handlers/capabilities/handler.go index 90bc2065edd..e1bdfdf8441 100644 --- a/core/services/gateway/handlers/capabilities/handler.go +++ b/core/services/gateway/handlers/capabilities/handler.go @@ -146,7 +146,8 @@ func (h *handler) handleWebAPIOutgoingMessage(ctx context.Context, msg *api.Mess newCtx := context.WithoutCancel(ctx) newCtx, cancel := context.WithTimeout(newCtx, timeout) defer cancel() - l := h.lggr.With("url", payload.URL, "messageId", msg.Body.MessageId, "method", payload.Method) + l := h.lggr.With("url", payload.URL, "messageId", msg.Body.MessageId, "method", payload.Method, "timeout", payload.TimeoutMs) + l.Debug("Sending request to client") respMsg, err := h.sendHTTPMessageToClient(newCtx, req, msg) if err != nil { l.Errorw("error while sending HTTP request to external endpoint", "err", err) @@ -187,7 +188,7 @@ func (h *handler) HandleNodeMessage(ctx context.Context, msg *api.Message, nodeA switch msg.Body.Method { case MethodWebAPITrigger: return h.handleWebAPITriggerMessage(ctx, msg, nodeAddr) - case MethodWebAPITarget, MethodComputeAction: + case MethodWebAPITarget, MethodComputeAction, MethodWorkflowSyncer: return h.handleWebAPIOutgoingMessage(ctx, msg, nodeAddr) default: return fmt.Errorf("unsupported method: %s", msg.Body.Method) diff --git a/core/services/gateway/network/httpclient.go b/core/services/gateway/network/httpclient.go index 4aecaaed3cd..52130c8d069 100644 --- a/core/services/gateway/network/httpclient.go +++ b/core/services/gateway/network/httpclient.go @@ -78,7 +78,7 @@ func (c *httpClient) Send(ctx context.Context, req HTTPRequest) (*HTTPResponse, // joining them to a single string in case array size is greater than 1 headers[k] = strings.Join(v, ",") } - c.lggr.Debugw("received HTTP response", "statusCode", resp.StatusCode, "body", string(body), "url", req.URL, "headers", headers) + c.lggr.Debugw("received HTTP response", "statusCode", resp.StatusCode, "url", req.URL, "headers", headers) return &HTTPResponse{ Headers: headers, diff --git a/core/services/job/mocks/orm.go b/core/services/job/mocks/orm.go index 89426b55a21..96513866f37 100644 --- a/core/services/job/mocks/orm.go +++ b/core/services/job/mocks/orm.go @@ -601,6 +601,63 @@ func (_c *ORM_FindJobIDByCapabilityNameAndVersion_Call) RunAndReturn(run func(co return _c } +// FindJobIDByStreamID provides a mock function with given fields: ctx, streamID +func (_m *ORM) FindJobIDByStreamID(ctx context.Context, streamID uint32) (int32, error) { + ret := _m.Called(ctx, streamID) + + if len(ret) == 0 { + panic("no return value specified for FindJobIDByStreamID") + } + + var r0 int32 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint32) (int32, error)); ok { + return rf(ctx, streamID) + } + if rf, ok := ret.Get(0).(func(context.Context, uint32) int32); ok { + r0 = rf(ctx, streamID) + } else { + r0 = ret.Get(0).(int32) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint32) error); ok { + r1 = rf(ctx, streamID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ORM_FindJobIDByStreamID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindJobIDByStreamID' +type ORM_FindJobIDByStreamID_Call struct { + *mock.Call +} + +// FindJobIDByStreamID is a helper method to define mock.On call +// - ctx context.Context +// - streamID uint32 +func (_e *ORM_Expecter) FindJobIDByStreamID(ctx interface{}, streamID interface{}) *ORM_FindJobIDByStreamID_Call { + return &ORM_FindJobIDByStreamID_Call{Call: _e.mock.On("FindJobIDByStreamID", ctx, streamID)} +} + +func (_c *ORM_FindJobIDByStreamID_Call) Run(run func(ctx context.Context, streamID uint32)) *ORM_FindJobIDByStreamID_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint32)) + }) + return _c +} + +func (_c *ORM_FindJobIDByStreamID_Call) Return(_a0 int32, _a1 error) *ORM_FindJobIDByStreamID_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ORM_FindJobIDByStreamID_Call) RunAndReturn(run func(context.Context, uint32) (int32, error)) *ORM_FindJobIDByStreamID_Call { + _c.Call.Return(run) + return _c +} + // FindJobIDByWorkflow provides a mock function with given fields: ctx, spec func (_m *ORM) FindJobIDByWorkflow(ctx context.Context, spec job.WorkflowSpec) (int32, error) { ret := _m.Called(ctx, spec) diff --git a/core/services/job/orm.go b/core/services/job/orm.go index 92ec9b2e83c..38e3fa492ce 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -78,6 +78,8 @@ type ORM interface { FindJobIDByWorkflow(ctx context.Context, spec WorkflowSpec) (int32, error) FindJobIDByCapabilityNameAndVersion(ctx context.Context, spec CCIPSpec) (int32, error) + + FindJobIDByStreamID(ctx context.Context, streamID uint32) (int32, error) } type ORMConfig interface { @@ -1334,6 +1336,20 @@ func (o *orm) FindJobsByPipelineSpecIDs(ctx context.Context, ids []int32) ([]Job return jbs, errors.Wrap(err, "FindJobsByPipelineSpecIDs failed") } +func (o *orm) FindJobIDByStreamID(ctx context.Context, streamID uint32) (jobID int32, err error) { + stmt := `SELECT id FROM jobs WHERE type = 'stream' AND stream_id = $1` + err = o.ds.GetContext(ctx, &jobID, stmt, streamID) + if err != nil { + if !errors.Is(err, sql.ErrNoRows) { + err = errors.Wrap(err, "error searching for job by stream id") + } + err = errors.Wrap(err, "FindJobIDByStreamID failed") + return + } + + return +} + // PipelineRuns returns pipeline runs for a job, with spec and taskruns loaded, latest first // If jobID is nil, returns all pipeline runs func (o *orm) PipelineRuns(ctx context.Context, jobID *int32, offset, size int) (runs []pipeline.Run, count int, err error) { diff --git a/core/services/keystore/keys/csakey/key_v2.go b/core/services/keystore/keys/csakey/key_v2.go index 08207f52af4..ddccbfb488b 100644 --- a/core/services/keystore/keys/csakey/key_v2.go +++ b/core/services/keystore/keys/csakey/key_v2.go @@ -16,7 +16,7 @@ func (raw Raw) Key() KeyV2 { privKey := ed25519.PrivateKey(raw) return KeyV2{ privateKey: &privKey, - PublicKey: ed25519PubKeyFromPrivKey(privKey), + PublicKey: privKey.Public().(ed25519.PublicKey), } } @@ -66,7 +66,7 @@ func MustNewV2XXXTestingOnly(k *big.Int) KeyV2 { privKey := ed25519.NewKeyFromSeed(seed) return KeyV2{ privateKey: &privKey, - PublicKey: ed25519PubKeyFromPrivKey(privKey), + PublicKey: privKey.Public().(ed25519.PublicKey), Version: 2, } } @@ -90,9 +90,3 @@ func (k KeyV2) String() string { func (k KeyV2) GoString() string { return k.String() } - -func ed25519PubKeyFromPrivKey(privKey ed25519.PrivateKey) ed25519.PublicKey { - publicKey := make([]byte, ed25519.PublicKeySize) - copy(publicKey, privKey[32:]) - return publicKey -} diff --git a/core/services/keystore/keys/ocr2key/evm_keyring.go b/core/services/keystore/keys/ocr2key/evm_keyring.go index 5d937e36a6e..554d655443d 100644 --- a/core/services/keystore/keys/ocr2key/evm_keyring.go +++ b/core/services/keystore/keys/ocr2key/evm_keyring.go @@ -60,7 +60,7 @@ func (ekr *evmKeyring) reportToSigData3(digest types.ConfigDigest, seqNr uint64, func RawReportContext3(digest types.ConfigDigest, seqNr uint64) [2][32]byte { seqNrBytes := [32]byte{} - binary.BigEndian.PutUint64(seqNrBytes[:], seqNr) + binary.BigEndian.PutUint64(seqNrBytes[24:], seqNr) return [2][32]byte{ digest, seqNrBytes, diff --git a/core/services/keystore/keys/ocr2key/evm_keyring_test.go b/core/services/keystore/keys/ocr2key/evm_keyring_test.go index 20ac197159a..85dad74eb88 100644 --- a/core/services/keystore/keys/ocr2key/evm_keyring_test.go +++ b/core/services/keystore/keys/ocr2key/evm_keyring_test.go @@ -3,6 +3,7 @@ package ocr2key import ( "bytes" cryptorand "crypto/rand" + "math" "math/rand" "testing" @@ -96,3 +97,66 @@ func TestEVMKeyring_Marshalling(t *testing.T) { // Invalid seed size should error assert.Error(t, kr2.Unmarshal([]byte{0x01})) } + +func TestRawReportContext3(t *testing.T) { + testCases := []struct { + name string + digest [32]byte + seqNr uint64 + expected [2][32]byte + }{ + { + name: "zero values", + digest: [32]byte{}, + seqNr: 0, + expected: [2][32]byte{ + {}, + {}, + }, + }, + { + name: "some digest", + digest: [32]byte{1, 2, 3}, + seqNr: 0, + expected: [2][32]byte{ + {1, 2, 3}, + {}, + }, + }, + { + name: "sequence number set to 1", + digest: [32]byte{}, + seqNr: 1, + expected: [2][32]byte{ + {}, + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, + }, + }, + }, + { + name: "sequence number set to max uint64", + digest: [32]byte{1, 2, 3}, + seqNr: math.MaxUint64, + expected: [2][32]byte{ + {1, 2, 3}, + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actual := RawReportContext3(tc.digest, tc.seqNr) + assert.Equal(t, tc.expected, actual, "unexpected result") + }) + } +} diff --git a/core/services/keystore/keys/ocr2key/key_bundle.go b/core/services/keystore/keys/ocr2key/key_bundle.go index 2c25a159fef..a08bd84ac30 100644 --- a/core/services/keystore/keys/ocr2key/key_bundle.go +++ b/core/services/keystore/keys/ocr2key/key_bundle.go @@ -19,7 +19,6 @@ type OCR3SignerVerifier interface { Verify3(publicKey ocrtypes.OnchainPublicKey, cd ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report, signature []byte) bool } -// nolint type KeyBundle interface { // OnchainKeyring is used for signing reports (groups of observations, verified onchain) ocrtypes.OnchainKeyring @@ -108,7 +107,6 @@ func (kb keyBundleBase) GoString() string { return kb.String() } -// nolint type Raw []byte func (raw Raw) Key() (kb KeyBundle) { diff --git a/core/services/keystore/keys/solkey/key.go b/core/services/keystore/keys/solkey/key.go index c6cdd62d3bf..610dada64b1 100644 --- a/core/services/keystore/keys/solkey/key.go +++ b/core/services/keystore/keys/solkey/key.go @@ -17,11 +17,9 @@ type Raw []byte // Key gets the Key func (raw Raw) Key() Key { privKey := ed25519.NewKeyFromSeed(raw) - pubKey := make([]byte, ed25519.PublicKeySize) - copy(pubKey, privKey[ed25519.PublicKeySize:]) return Key{ privkey: privKey, - pubKey: pubKey, + pubKey: privKey.Public().(ed25519.PublicKey), } } diff --git a/core/services/keystore/keys/workflowkey/key.go b/core/services/keystore/keys/workflowkey/key.go index ce8560303e0..084878a5ee3 100644 --- a/core/services/keystore/keys/workflowkey/key.go +++ b/core/services/keystore/keys/workflowkey/key.go @@ -50,10 +50,18 @@ func New() (Key, error) { } func (k Key) PublicKey() [curve25519.PointSize]byte { + if k.publicKey == nil { + return [curve25519.PointSize]byte{} + } + return *k.publicKey } func (k Key) PublicKeyString() string { + if k.publicKey == nil { + return "" + } + return hex.EncodeToString(k.publicKey[:]) } @@ -78,6 +86,10 @@ func (k Key) GoString() string { // Encrypt encrypts a message using the public key func (k Key) Encrypt(plaintext []byte) ([]byte, error) { publicKey := k.PublicKey() + if publicKey == [curve25519.PointSize]byte{} { + return nil, errors.New("public key is empty") + } + encrypted, err := box.SealAnonymous(nil, plaintext, &publicKey, cryptorand.Reader) if err != nil { return nil, err @@ -89,6 +101,10 @@ func (k Key) Encrypt(plaintext []byte) ([]byte, error) { // Decrypt decrypts a message that was encrypted using the private key func (k Key) Decrypt(ciphertext []byte) (plaintext []byte, err error) { publicKey := k.PublicKey() + if publicKey == [curve25519.PointSize]byte{} { + return nil, errors.New("public key is empty") + } + decrypted, success := box.OpenAnonymous(nil, ciphertext, &publicKey, k.privateKey) if !success { return nil, errors.New("decryption failed") diff --git a/core/services/keystore/keystoretest.go b/core/services/keystore/keystoretest.go index e179b51bb54..626cc4bab99 100644 --- a/core/services/keystore/keystoretest.go +++ b/core/services/keystore/keystoretest.go @@ -75,5 +75,6 @@ func NewInMemory(ds sqlutil.DataSource, scryptParams utils.ScryptParams, lggr lo starknet: newStarkNetKeyStore(km), aptos: newAptosKeyStore(km), vrf: newVRFKeyStore(km), + workflow: newWorkflowKeyStore(km), } } diff --git a/core/services/keystore/mocks/workflow.go b/core/services/keystore/mocks/workflow.go new file mode 100644 index 00000000000..f19045cecc4 --- /dev/null +++ b/core/services/keystore/mocks/workflow.go @@ -0,0 +1,474 @@ +// Code generated by mockery v2.46.3. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + + workflowkey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" +) + +// Workflow is an autogenerated mock type for the Workflow type +type Workflow struct { + mock.Mock +} + +type Workflow_Expecter struct { + mock *mock.Mock +} + +func (_m *Workflow) EXPECT() *Workflow_Expecter { + return &Workflow_Expecter{mock: &_m.Mock} +} + +// Add provides a mock function with given fields: ctx, key +func (_m *Workflow) Add(ctx context.Context, key workflowkey.Key) error { + ret := _m.Called(ctx, key) + + if len(ret) == 0 { + panic("no return value specified for Add") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, workflowkey.Key) error); ok { + r0 = rf(ctx, key) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Workflow_Add_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Add' +type Workflow_Add_Call struct { + *mock.Call +} + +// Add is a helper method to define mock.On call +// - ctx context.Context +// - key workflowkey.Key +func (_e *Workflow_Expecter) Add(ctx interface{}, key interface{}) *Workflow_Add_Call { + return &Workflow_Add_Call{Call: _e.mock.On("Add", ctx, key)} +} + +func (_c *Workflow_Add_Call) Run(run func(ctx context.Context, key workflowkey.Key)) *Workflow_Add_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(workflowkey.Key)) + }) + return _c +} + +func (_c *Workflow_Add_Call) Return(_a0 error) *Workflow_Add_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Workflow_Add_Call) RunAndReturn(run func(context.Context, workflowkey.Key) error) *Workflow_Add_Call { + _c.Call.Return(run) + return _c +} + +// Create provides a mock function with given fields: ctx +func (_m *Workflow) Create(ctx context.Context) (workflowkey.Key, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for Create") + } + + var r0 workflowkey.Key + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (workflowkey.Key, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) workflowkey.Key); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(workflowkey.Key) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Workflow_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' +type Workflow_Create_Call struct { + *mock.Call +} + +// Create is a helper method to define mock.On call +// - ctx context.Context +func (_e *Workflow_Expecter) Create(ctx interface{}) *Workflow_Create_Call { + return &Workflow_Create_Call{Call: _e.mock.On("Create", ctx)} +} + +func (_c *Workflow_Create_Call) Run(run func(ctx context.Context)) *Workflow_Create_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Workflow_Create_Call) Return(_a0 workflowkey.Key, _a1 error) *Workflow_Create_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Workflow_Create_Call) RunAndReturn(run func(context.Context) (workflowkey.Key, error)) *Workflow_Create_Call { + _c.Call.Return(run) + return _c +} + +// Delete provides a mock function with given fields: ctx, id +func (_m *Workflow) Delete(ctx context.Context, id string) (workflowkey.Key, error) { + ret := _m.Called(ctx, id) + + if len(ret) == 0 { + panic("no return value specified for Delete") + } + + var r0 workflowkey.Key + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (workflowkey.Key, error)); ok { + return rf(ctx, id) + } + if rf, ok := ret.Get(0).(func(context.Context, string) workflowkey.Key); ok { + r0 = rf(ctx, id) + } else { + r0 = ret.Get(0).(workflowkey.Key) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Workflow_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' +type Workflow_Delete_Call struct { + *mock.Call +} + +// Delete is a helper method to define mock.On call +// - ctx context.Context +// - id string +func (_e *Workflow_Expecter) Delete(ctx interface{}, id interface{}) *Workflow_Delete_Call { + return &Workflow_Delete_Call{Call: _e.mock.On("Delete", ctx, id)} +} + +func (_c *Workflow_Delete_Call) Run(run func(ctx context.Context, id string)) *Workflow_Delete_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *Workflow_Delete_Call) Return(_a0 workflowkey.Key, _a1 error) *Workflow_Delete_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Workflow_Delete_Call) RunAndReturn(run func(context.Context, string) (workflowkey.Key, error)) *Workflow_Delete_Call { + _c.Call.Return(run) + return _c +} + +// EnsureKey provides a mock function with given fields: ctx +func (_m *Workflow) EnsureKey(ctx context.Context) error { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for EnsureKey") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Workflow_EnsureKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnsureKey' +type Workflow_EnsureKey_Call struct { + *mock.Call +} + +// EnsureKey is a helper method to define mock.On call +// - ctx context.Context +func (_e *Workflow_Expecter) EnsureKey(ctx interface{}) *Workflow_EnsureKey_Call { + return &Workflow_EnsureKey_Call{Call: _e.mock.On("EnsureKey", ctx)} +} + +func (_c *Workflow_EnsureKey_Call) Run(run func(ctx context.Context)) *Workflow_EnsureKey_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Workflow_EnsureKey_Call) Return(_a0 error) *Workflow_EnsureKey_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Workflow_EnsureKey_Call) RunAndReturn(run func(context.Context) error) *Workflow_EnsureKey_Call { + _c.Call.Return(run) + return _c +} + +// Export provides a mock function with given fields: id, password +func (_m *Workflow) Export(id string, password string) ([]byte, error) { + ret := _m.Called(id, password) + + if len(ret) == 0 { + panic("no return value specified for Export") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(string, string) ([]byte, error)); ok { + return rf(id, password) + } + if rf, ok := ret.Get(0).(func(string, string) []byte); ok { + r0 = rf(id, password) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(string, string) error); ok { + r1 = rf(id, password) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Workflow_Export_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Export' +type Workflow_Export_Call struct { + *mock.Call +} + +// Export is a helper method to define mock.On call +// - id string +// - password string +func (_e *Workflow_Expecter) Export(id interface{}, password interface{}) *Workflow_Export_Call { + return &Workflow_Export_Call{Call: _e.mock.On("Export", id, password)} +} + +func (_c *Workflow_Export_Call) Run(run func(id string, password string)) *Workflow_Export_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(string)) + }) + return _c +} + +func (_c *Workflow_Export_Call) Return(_a0 []byte, _a1 error) *Workflow_Export_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Workflow_Export_Call) RunAndReturn(run func(string, string) ([]byte, error)) *Workflow_Export_Call { + _c.Call.Return(run) + return _c +} + +// Get provides a mock function with given fields: id +func (_m *Workflow) Get(id string) (workflowkey.Key, error) { + ret := _m.Called(id) + + if len(ret) == 0 { + panic("no return value specified for Get") + } + + var r0 workflowkey.Key + var r1 error + if rf, ok := ret.Get(0).(func(string) (workflowkey.Key, error)); ok { + return rf(id) + } + if rf, ok := ret.Get(0).(func(string) workflowkey.Key); ok { + r0 = rf(id) + } else { + r0 = ret.Get(0).(workflowkey.Key) + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Workflow_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' +type Workflow_Get_Call struct { + *mock.Call +} + +// Get is a helper method to define mock.On call +// - id string +func (_e *Workflow_Expecter) Get(id interface{}) *Workflow_Get_Call { + return &Workflow_Get_Call{Call: _e.mock.On("Get", id)} +} + +func (_c *Workflow_Get_Call) Run(run func(id string)) *Workflow_Get_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Workflow_Get_Call) Return(_a0 workflowkey.Key, _a1 error) *Workflow_Get_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Workflow_Get_Call) RunAndReturn(run func(string) (workflowkey.Key, error)) *Workflow_Get_Call { + _c.Call.Return(run) + return _c +} + +// GetAll provides a mock function with given fields: +func (_m *Workflow) GetAll() ([]workflowkey.Key, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetAll") + } + + var r0 []workflowkey.Key + var r1 error + if rf, ok := ret.Get(0).(func() ([]workflowkey.Key, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() []workflowkey.Key); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]workflowkey.Key) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Workflow_GetAll_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAll' +type Workflow_GetAll_Call struct { + *mock.Call +} + +// GetAll is a helper method to define mock.On call +func (_e *Workflow_Expecter) GetAll() *Workflow_GetAll_Call { + return &Workflow_GetAll_Call{Call: _e.mock.On("GetAll")} +} + +func (_c *Workflow_GetAll_Call) Run(run func()) *Workflow_GetAll_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Workflow_GetAll_Call) Return(_a0 []workflowkey.Key, _a1 error) *Workflow_GetAll_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Workflow_GetAll_Call) RunAndReturn(run func() ([]workflowkey.Key, error)) *Workflow_GetAll_Call { + _c.Call.Return(run) + return _c +} + +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *Workflow) Import(ctx context.Context, keyJSON []byte, password string) (workflowkey.Key, error) { + ret := _m.Called(ctx, keyJSON, password) + + if len(ret) == 0 { + panic("no return value specified for Import") + } + + var r0 workflowkey.Key + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (workflowkey.Key, error)); ok { + return rf(ctx, keyJSON, password) + } + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) workflowkey.Key); ok { + r0 = rf(ctx, keyJSON, password) + } else { + r0 = ret.Get(0).(workflowkey.Key) + } + + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Workflow_Import_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Import' +type Workflow_Import_Call struct { + *mock.Call +} + +// Import is a helper method to define mock.On call +// - ctx context.Context +// - keyJSON []byte +// - password string +func (_e *Workflow_Expecter) Import(ctx interface{}, keyJSON interface{}, password interface{}) *Workflow_Import_Call { + return &Workflow_Import_Call{Call: _e.mock.On("Import", ctx, keyJSON, password)} +} + +func (_c *Workflow_Import_Call) Run(run func(ctx context.Context, keyJSON []byte, password string)) *Workflow_Import_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]byte), args[2].(string)) + }) + return _c +} + +func (_c *Workflow_Import_Call) Return(_a0 workflowkey.Key, _a1 error) *Workflow_Import_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Workflow_Import_Call) RunAndReturn(run func(context.Context, []byte, string) (workflowkey.Key, error)) *Workflow_Import_Call { + _c.Call.Return(run) + return _c +} + +// NewWorkflow creates a new instance of Workflow. 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 NewWorkflow(t interface { + mock.TestingT + Cleanup(func()) +}) *Workflow { + mock := &Workflow{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/keystore/models.go b/core/services/keystore/models.go index e0b53ef95e4..151934827c3 100644 --- a/core/services/keystore/models.go +++ b/core/services/keystore/models.go @@ -239,6 +239,9 @@ func (kr *keyRing) raw() (rawKeys rawKeyRing) { for _, vrfKey := range kr.VRF { rawKeys.VRF = append(rawKeys.VRF, vrfKey.Raw()) } + for _, workflowKey := range kr.Workflow { + rawKeys.Workflow = append(rawKeys.Workflow, workflowKey.Raw()) + } return rawKeys } @@ -284,6 +287,12 @@ func (kr *keyRing) logPubKeys(lggr logger.Logger) { for _, VRFKey := range kr.VRF { vrfIDs = append(vrfIDs, VRFKey.ID()) } + workflowIDs := make([]string, len(kr.Workflow)) + i := 0 + for _, workflowKey := range kr.Workflow { + workflowIDs[i] = workflowKey.ID() + i++ + } if len(csaIDs) > 0 { lggr.Infow(fmt.Sprintf("Unlocked %d CSA keys", len(csaIDs)), "keys", csaIDs) } @@ -314,6 +323,9 @@ func (kr *keyRing) logPubKeys(lggr logger.Logger) { if len(vrfIDs) > 0 { lggr.Infow(fmt.Sprintf("Unlocked %d VRF keys", len(vrfIDs)), "keys", vrfIDs) } + if len(workflowIDs) > 0 { + lggr.Infow(fmt.Sprintf("Unlocked %d Workflow keys", len(workflowIDs)), "keys", workflowIDs) + } if len(kr.LegacyKeys.legacyRawKeys) > 0 { lggr.Infow(fmt.Sprintf("%d keys stored in legacy system", kr.LegacyKeys.legacyRawKeys.len())) } @@ -333,6 +345,7 @@ type rawKeyRing struct { StarkNet []starkkey.Raw Aptos []aptoskey.Raw VRF []vrfkey.Raw + Workflow []workflowkey.Raw LegacyKeys LegacyKeyStorage `json:"-"` } @@ -379,6 +392,10 @@ func (rawKeys rawKeyRing) keys() (*keyRing, error) { vrfKey := rawVRFKey.Key() keyRing.VRF[vrfKey.ID()] = vrfKey } + for _, rawWorkflowKey := range rawKeys.Workflow { + workflowKey := rawWorkflowKey.Key() + keyRing.Workflow[workflowKey.ID()] = workflowKey + } keyRing.LegacyKeys = rawKeys.LegacyKeys return keyRing, nil diff --git a/core/services/keystore/workflow_test.go b/core/services/keystore/workflow_test.go index 051ebdb76a7..d7e540b9c75 100644 --- a/core/services/keystore/workflow_test.go +++ b/core/services/keystore/workflow_test.go @@ -175,4 +175,39 @@ func Test_EncryptionKeyStore_E2E(t *testing.T) { require.NoError(t, err) require.Len(t, keys, 1) }) + + t.Run("persists keys across restarts", func(t *testing.T) { + defer reset() + ctx := testutils.Context(t) + + keys, err := ks.GetAll() + require.NoError(t, err) + assert.Empty(t, keys) + + err = keyStore.Workflow().EnsureKey(ctx) + require.NoError(t, err) + + keys, err = ks.GetAll() + require.NoError(t, err) + + require.NoError(t, err) + require.Len(t, keys, 1) + + // Now instantiate the keystore again, but with the same DB + // This should fetch the key directly from the DB. + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) + + gotKeys, err := keyStore.Workflow().GetAll() + require.NoError(t, err) + require.Len(t, gotKeys, 1) + + assert.Equal(t, keys[0].PublicKeyString(), gotKeys[0].PublicKeyString()) + + err = keyStore.Workflow().EnsureKey(testutils.Context(t)) + require.NoError(t, err) + gotKeys, err = keyStore.Workflow().GetAll() + require.NoError(t, err) + require.Len(t, gotKeys, 1) + }) } diff --git a/core/services/llo/delegate.go b/core/services/llo/delegate.go index d305fe0e948..ba4ddbb8fb0 100644 --- a/core/services/llo/delegate.go +++ b/core/services/llo/delegate.go @@ -21,6 +21,7 @@ import ( corelogger "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr3/promwrapper" "github.com/smartcontractkit/chainlink/v2/core/services/streams" ) @@ -59,6 +60,7 @@ type DelegateConfig struct { ShouldRetireCache datastreamsllo.ShouldRetireCache EAMonitoringEndpoint ocrcommontypes.MonitoringEndpoint DonID uint32 + ChainID string // OCR3 TraceLogging bool @@ -151,8 +153,21 @@ func (d *delegate) Start(ctx context.Context) error { OffchainConfigDigester: d.cfg.OffchainConfigDigester, OffchainKeyring: d.cfg.OffchainKeyring, OnchainKeyring: d.cfg.OnchainKeyring, - ReportingPluginFactory: datastreamsllo.NewPluginFactory( - d.cfg.ReportingPluginConfig, psrrc, d.src, d.cfg.RetirementReportCodec, d.cfg.ChannelDefinitionCache, d.ds, logger.Named(lggr, "ReportingPlugin"), llo.EVMOnchainConfigCodec{}, d.reportCodecs, + ReportingPluginFactory: promwrapper.NewReportingPluginFactory( + datastreamsllo.NewPluginFactory( + d.cfg.ReportingPluginConfig, + psrrc, + d.src, + d.cfg.RetirementReportCodec, + d.cfg.ChannelDefinitionCache, + d.ds, + logger.Named(lggr, "ReportingPlugin"), + llo.EVMOnchainConfigCodec{}, + d.reportCodecs, + ), + lggr, + d.cfg.ChainID, + "llo", ), MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": d.cfg.JobName.ValueOrZero()}, prometheus.DefaultRegisterer), }) diff --git a/core/services/llo/evm/report_codec_premium_legacy.go b/core/services/llo/evm/report_codec_premium_legacy.go index e38f6db7781..fdbad6aead9 100644 --- a/core/services/llo/evm/report_codec_premium_legacy.go +++ b/core/services/llo/evm/report_codec_premium_legacy.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "math" "math/big" "github.com/ethereum/go-ethereum/common" @@ -14,11 +15,11 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2/types" ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" v3 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" "github.com/smartcontractkit/chainlink-data-streams/llo" - "github.com/smartcontractkit/chainlink-common/pkg/logger" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" reportcodecv3 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/reportcodec" @@ -121,7 +122,10 @@ func (r ReportCodecPremiumLegacy) Pack(digest types.ConfigDigest, seqNr uint64, ss = append(ss, s) vs[i] = v } - reportCtx := LegacyReportContext(digest, seqNr, r.donID) + reportCtx, err := LegacyReportContext(digest, seqNr, r.donID) + if err != nil { + return nil, fmt.Errorf("failed to get legacy report context: %w", err) + } rawReportCtx := evmutil.RawReportContext(reportCtx) payload, err := mercury.PayloadTypes.Pack(rawReportCtx, []byte(report), rs, ss, vs) @@ -203,21 +207,28 @@ func LLOExtraHash(donID uint32) common.Hash { return common.BigToHash(new(big.Int).SetUint64(combined)) } -func SeqNrToEpochAndRound(seqNr uint64) (epoch uint32, round uint8) { +func SeqNrToEpochAndRound(seqNr uint64) (epoch uint32, round uint8, err error) { // Simulate 256 rounds/epoch - epoch = uint32(seqNr / 256) // nolint - round = uint8(seqNr % 256) // nolint + if seqNr/256 > math.MaxUint32 { + err = fmt.Errorf("epoch overflows uint32: %d", seqNr) + return + } + epoch = uint32(seqNr / 256) //nolint:gosec // G115 false positive + round = uint8(seqNr % 256) //nolint:gosec // G115 false positive return } -func LegacyReportContext(cd ocr2types.ConfigDigest, seqNr uint64, donID uint32) ocr2types.ReportContext { - epoch, round := SeqNrToEpochAndRound(seqNr) +func LegacyReportContext(cd ocr2types.ConfigDigest, seqNr uint64, donID uint32) (ocr2types.ReportContext, error) { + epoch, round, err := SeqNrToEpochAndRound(seqNr) + if err != nil { + return ocr2types.ReportContext{}, err + } return ocr2types.ReportContext{ ReportTimestamp: ocr2types.ReportTimestamp{ ConfigDigest: cd, - Epoch: uint32(epoch), - Round: uint8(round), + Epoch: epoch, + Round: round, }, ExtraHash: LLOExtraHash(donID), // ExtraHash is always zero for mercury, we use LLOExtraHash here to differentiate from the legacy plugin - } + }, nil } diff --git a/core/services/llo/evm/report_codec_premium_legacy_test.go b/core/services/llo/evm/report_codec_premium_legacy_test.go index 26176bb0243..a88626e6c57 100644 --- a/core/services/llo/evm/report_codec_premium_legacy_test.go +++ b/core/services/llo/evm/report_codec_premium_legacy_test.go @@ -20,6 +20,28 @@ import ( "github.com/smartcontractkit/chainlink-data-streams/llo" ) +func FuzzReportCodecPremiumLegacy_Decode(f *testing.F) { + f.Add([]byte("not a protobuf")) + f.Add([]byte{0x0a, 0x00}) // empty protobuf + f.Add([]byte{0x0a, 0x02, 0x08, 0x01}) // invalid protobuf + f.Add(([]byte)(nil)) + f.Add([]byte{}) + + validReport := newValidPremiumLegacyReport() + feedID := [32]uint8{0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} + cd := llotypes.ChannelDefinition{Opts: llotypes.ChannelOpts(fmt.Sprintf(`{"baseUSDFee":"10.50","expirationWindow":60,"feedId":"0x%x","multiplier":10}`, feedID))} + + codec := ReportCodecPremiumLegacy{logger.NullLogger, 100002} + + validEncodedReport, err := codec.Encode(tests.Context(f), validReport, cd) + require.NoError(f, err) + f.Add(validEncodedReport) + + f.Fuzz(func(t *testing.T, data []byte) { + codec.Decode(data) //nolint:errcheck // test that it doesn't panic, don't care about errors + }) +} + func newValidPremiumLegacyReport() llo.Report { return llo.Report{ ConfigDigest: types.ConfigDigest{1, 2, 3}, diff --git a/core/services/llo/keyring.go b/core/services/llo/keyring.go index dee223b4531..d4bf615711c 100644 --- a/core/services/llo/keyring.go +++ b/core/services/llo/keyring.go @@ -84,7 +84,10 @@ func (okr *onchainKeyring) Sign(digest types.ConfigDigest, seqNr uint64, r ocr3t rf := r.Info.ReportFormat if key, exists := okr.keys[rf]; exists { // NOTE: Must use legacy Sign method for compatibility with v0.3 report verification - rc := evm.LegacyReportContext(digest, seqNr, okr.donID) + rc, err := evm.LegacyReportContext(digest, seqNr, okr.donID) + if err != nil { + return nil, fmt.Errorf("failed to get legacy report context: %w", err) + } return key.Sign(rc, r.Report) } default: @@ -102,7 +105,11 @@ func (okr *onchainKeyring) Verify(key types.OnchainPublicKey, digest types.Confi rf := r.Info.ReportFormat if verifier, exists := okr.keys[rf]; exists { // NOTE: Must use legacy Verify method for compatibility with v0.3 report verification - rc := evm.LegacyReportContext(digest, seqNr, okr.donID) + rc, err := evm.LegacyReportContext(digest, seqNr, okr.donID) + if err != nil { + okr.lggr.Errorw("Verify failed; unable to get legacy report context", "err", err) + return false + } return verifier.Verify(key, rc, r.Report, signature) } default: diff --git a/core/services/llo/keyring_test.go b/core/services/llo/keyring_test.go index 3a0f8c5650b..b50e8d169c0 100644 --- a/core/services/llo/keyring_test.go +++ b/core/services/llo/keyring_test.go @@ -2,13 +2,14 @@ package llo import ( "fmt" - "math/rand" + "math" + "math/rand/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - ocr3types "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" @@ -83,7 +84,7 @@ func Test_Keyring(t *testing.T) { cd, err := ocrtypes.BytesToConfigDigest(testutils.MustRandBytes(32)) require.NoError(t, err) - seqNr := rand.Uint64() + seqNr := rand.Uint64N(math.MaxUint32 << 8) t.Run("Sign+Verify", func(t *testing.T) { for _, tc := range cases { t.Run(tc.format.String(), func(t *testing.T) { diff --git a/core/services/llo/mercurytransmitter/orm.go b/core/services/llo/mercurytransmitter/orm.go index ed8c8843f4c..045161395b5 100644 --- a/core/services/llo/mercurytransmitter/orm.go +++ b/core/services/llo/mercurytransmitter/orm.go @@ -72,7 +72,7 @@ func (o *orm) Insert(ctx context.Context, transmissions []*Transmission) error { DonID: o.donID, ServerURL: t.ServerURL, ConfigDigest: t.ConfigDigest, - SeqNr: int64(t.SeqNr), //nolint + SeqNr: int64(t.SeqNr), //nolint:gosec // G115 false positive Report: t.Report.Report, LifecycleStage: string(t.Report.Info.LifeCycleStage), ReportFormat: uint32(t.Report.Info.ReportFormat), @@ -162,7 +162,7 @@ func (o *orm) Get(ctx context.Context, serverURL string) ([]*Transmission, error } transmission.Sigs = append(transmission.Sigs, ocrtypes.AttributedOnchainSignature{ Signature: sig, - Signer: commontypes.OracleID(signers[i]), //nolint + Signer: commontypes.OracleID(signers[i]), //nolint:gosec // G115 false positive }) } diff --git a/core/services/llo/onchain_channel_definition_cache_test.go b/core/services/llo/onchain_channel_definition_cache_test.go index fa5a26237e5..e6ea3264273 100644 --- a/core/services/llo/onchain_channel_definition_cache_test.go +++ b/core/services/llo/onchain_channel_definition_cache_test.go @@ -298,7 +298,7 @@ func Test_ChannelDefinitionCache(t *testing.T) { } t.Run("nil ctx returns error", func(t *testing.T) { - _, err := cdc.fetchChannelDefinitions(nil, "notvalid://foos", [32]byte{}) //nolint + _, err := cdc.fetchChannelDefinitions(nil, "notvalid://foos", [32]byte{}) //nolint:staticcheck // SA1012 we pass nil intentionally here assert.EqualError(t, err, "failed to create http.Request; net/http: nil Context") }) diff --git a/core/services/llo/plugin_scoped_retirement_report_cache_test.go b/core/services/llo/plugin_scoped_retirement_report_cache_test.go index e1afb203fd2..f370cd9f1b4 100644 --- a/core/services/llo/plugin_scoped_retirement_report_cache_test.go +++ b/core/services/llo/plugin_scoped_retirement_report_cache_test.go @@ -16,6 +16,25 @@ import ( llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" ) +func FuzzPluginScopedRetirementReportCache_CheckAttestedRetirementReport(f *testing.F) { + f.Add([]byte("not a protobuf")) + f.Add([]byte{0x0a, 0x00}) // empty protobuf + f.Add([]byte{0x0a, 0x02, 0x08, 0x01}) // invalid protobuf + f.Add(([]byte)(nil)) + f.Add([]byte{}) + + rrc := &mockRetirementReportCache{} + v := &mockVerifier{} + c := &mockCodec{} + psrrc := NewPluginScopedRetirementReportCache(rrc, v, c) + + exampleDigest := ocr2types.ConfigDigest{1} + + f.Fuzz(func(t *testing.T, data []byte) { + psrrc.CheckAttestedRetirementReport(exampleDigest, data) //nolint:errcheck // test that it doesn't panic, don't care about errors + }) +} + type mockRetirementReportCache struct { arr []byte cfg Config diff --git a/core/services/llo/telemetry.go b/core/services/llo/telemetry.go index bb86679dc52..0b315d78d2b 100644 --- a/core/services/llo/telemetry.go +++ b/core/services/llo/telemetry.go @@ -119,7 +119,6 @@ func (t *telemeter) collectV3PremiumLegacyTelemetry(d TelemetryObservation) { askPrice = v.Ask.IntPart() ask = v.Ask.String() } - epoch, round := evm.SeqNrToEpochAndRound(d.opts.OutCtx().SeqNr) tea := &telem.EnhancedEAMercury{ DataSource: eaTelem.DataSource, DpBenchmarkPrice: eaTelem.DpBenchmarkPrice, @@ -142,12 +141,17 @@ func (t *telemeter) collectV3PremiumLegacyTelemetry(d TelemetryObservation) { IsLinkFeed: false, IsNativeFeed: false, ConfigDigest: d.opts.ConfigDigest().Hex(), - Round: int64(round), - Epoch: int64(epoch), AssetSymbol: eaTelem.AssetSymbol, Version: uint32(1000 + mercuryutils.REPORT_V3), // add 1000 to distinguish between legacy feeds, this can be changed if necessary DonId: t.donID, } + epoch, round, err := evm.SeqNrToEpochAndRound(d.opts.OutCtx().SeqNr) + if err != nil { + t.eng.SugaredLogger.Warnw("Failed to convert sequence number to epoch and round", "err", err) + } else { + tea.Round = int64(round) + tea.Epoch = int64(epoch) + } bytes, err := proto.Marshal(tea) if err != nil { diff --git a/core/services/ocr/database.go b/core/services/ocr/database.go index b5f890565f1..b570c89e5a2 100644 --- a/core/services/ocr/database.go +++ b/core/services/ocr/database.go @@ -209,7 +209,7 @@ func (d *db) StorePendingTransmission(ctx context.Context, k ocrtypes.ReportTime } func (d *db) PendingTransmissionsWithConfigDigest(ctx context.Context, cd ocrtypes.ConfigDigest) (map[ocrtypes.ReportTimestamp]ocrtypes.PendingTransmission, error) { - //nolint sqlclosecheck false positive + //nolint:sqlclosecheck // false positive rows, err := d.ds.QueryContext(ctx, ` SELECT config_digest, diff --git a/core/services/ocr2/database.go b/core/services/ocr2/database.go index 919d8ff5741..11de288432f 100644 --- a/core/services/ocr2/database.go +++ b/core/services/ocr2/database.go @@ -278,7 +278,7 @@ func (d *db) PendingTransmissionsWithConfigDigest(ctx context.Context, cd ocrtyp FROM ocr2_pending_transmissions WHERE ocr2_oracle_spec_id = $1 AND config_digest = $2 ` - rows, err := d.ds.QueryxContext(ctx, stmt, d.oracleSpecID, cd) //nolint sqlclosecheck false positive + rows, err := d.ds.QueryxContext(ctx, stmt, d.oracleSpecID, cd) if err != nil { return nil, errors.Wrap(err, "PendingTransmissionsWithConfigDigest failed to query rows") } diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index e7a5a1c3a92..edcc816bf04 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -1048,6 +1048,7 @@ func (d *Delegate) newServicesLLO( RetirementReportCodec: datastreamsllo.StandardRetirementReportCodec{}, EAMonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, telemetryContractID, synchronization.EnhancedEAMercury), DonID: pluginCfg.DonID, + ChainID: rid.ChainID, TraceLogging: d.cfg.OCR2().TraceLogging(), BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, diff --git a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go index fb59c0d0783..ddae5241883 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go @@ -23,11 +23,11 @@ import ( "github.com/jmoiron/sqlx" "github.com/onsi/gomega" "github.com/pkg/errors" + "k8s.io/utils/ptr" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "go.uber.org/zap" - "k8s.io/utils/pointer" //nolint:staticcheck "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2/confighelper" @@ -387,7 +387,7 @@ func setupNodeCCIP( c.Feature.UICSAKeys = &trueRef c.Feature.FeedsManager = &trueRef c.OCR.Enabled = &falseRef - c.OCR.DefaultTransactionQueueDepth = pointer.Uint32(200) + c.OCR.DefaultTransactionQueueDepth = ptr.To[uint32](200) c.OCR2.Enabled = &trueRef c.Feature.LogPoller = &trueRef c.P2P.V2.Enabled = &trueRef diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go index c80b376a2af..30aaebd4e9e 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go @@ -22,11 +22,11 @@ import ( "github.com/jmoiron/sqlx" "github.com/onsi/gomega" "github.com/pkg/errors" + "k8s.io/utils/ptr" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "go.uber.org/zap" - "k8s.io/utils/pointer" //nolint:staticcheck "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2/confighelper" @@ -383,7 +383,7 @@ func setupNodeCCIP( c.Feature.UICSAKeys = &trueRef c.Feature.FeedsManager = &trueRef c.OCR.Enabled = &falseRef - c.OCR.DefaultTransactionQueueDepth = pointer.Uint32(200) + c.OCR.DefaultTransactionQueueDepth = ptr.To[uint32](200) c.OCR2.Enabled = &trueRef c.Feature.LogPoller = &trueRef c.P2P.V2.Enabled = &trueRef diff --git a/core/services/ocr2/plugins/generic/relayerset_test.go b/core/services/ocr2/plugins/generic/relayerset_test.go index 44ed216520f..cd9d28ffd60 100644 --- a/core/services/ocr2/plugins/generic/relayerset_test.go +++ b/core/services/ocr2/plugins/generic/relayerset_test.go @@ -150,7 +150,7 @@ func (t *TestRelayer) Ready() error { panic("implement me") } func (t *TestRelayer) HealthReport() map[string]error { panic("implement me") } -func (t *TestRelayer) NewChainWriter(_ context.Context, _ []byte) (types.ChainWriter, error) { +func (t *TestRelayer) NewContractWriter(_ context.Context, _ []byte) (types.ContractWriter, error) { panic("implement me") } diff --git a/core/services/ocr3/promwrapper/factory.go b/core/services/ocr3/promwrapper/factory.go new file mode 100644 index 00000000000..6518cea3c0d --- /dev/null +++ b/core/services/ocr3/promwrapper/factory.go @@ -0,0 +1,53 @@ +package promwrapper + +import ( + "context" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" +) + +var _ ocr3types.ReportingPluginFactory[any] = &ReportingPluginFactory[any]{} + +type ReportingPluginFactory[RI any] struct { + origin ocr3types.ReportingPluginFactory[RI] + lggr logger.Logger + chainID string + plugin string +} + +func NewReportingPluginFactory[RI any]( + origin ocr3types.ReportingPluginFactory[RI], + lggr logger.Logger, + chainID string, + plugin string, +) *ReportingPluginFactory[RI] { + return &ReportingPluginFactory[RI]{ + origin: origin, + lggr: lggr, + chainID: chainID, + plugin: plugin, + } +} + +func (r ReportingPluginFactory[RI]) NewReportingPlugin(ctx context.Context, config ocr3types.ReportingPluginConfig) (ocr3types.ReportingPlugin[RI], ocr3types.ReportingPluginInfo, error) { + plugin, info, err := r.origin.NewReportingPlugin(ctx, config) + if err != nil { + return nil, ocr3types.ReportingPluginInfo{}, err + } + r.lggr.Infow("Wrapping ReportingPlugin with prometheus metrics reporter", + "configDigest", config.ConfigDigest, + "oracleID", config.OracleID, + ) + wrapped := newReportingPlugin( + plugin, + r.chainID, + r.plugin, + config.ConfigDigest.String(), + promOCR3ReportsGenerated, + promOCR3Durations, + promOCR3PluginStatus, + ) + return wrapped, info, err +} diff --git a/core/services/ocr3/promwrapper/factory_test.go b/core/services/ocr3/promwrapper/factory_test.go new file mode 100644 index 00000000000..fb68c039b78 --- /dev/null +++ b/core/services/ocr3/promwrapper/factory_test.go @@ -0,0 +1,43 @@ +package promwrapper + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func Test_WrapperFactory(t *testing.T) { + validFactory := NewReportingPluginFactory(fakeFactory[uint]{}, logger.TestLogger(t), "solana", "plugin") + failingFactory := NewReportingPluginFactory(fakeFactory[uint]{err: errors.New("error")}, logger.TestLogger(t), "123", "plugin") + + plugin, _, err := validFactory.NewReportingPlugin(tests.Context(t), ocr3types.ReportingPluginConfig{}) + require.NoError(t, err) + + _, err = plugin.Outcome(tests.Context(t), ocr3types.OutcomeContext{}, nil, nil) + require.NoError(t, err) + + require.Equal(t, 1, counterFromHistogramByLabels(t, promOCR3Durations, "solana", "plugin", "outcome", "true")) + require.Equal(t, 0, counterFromHistogramByLabels(t, promOCR3Durations, "solana", "plugin", "outcome", "false")) + + _, _, err = failingFactory.NewReportingPlugin(tests.Context(t), ocr3types.ReportingPluginConfig{}) + require.Error(t, err) +} + +type fakeFactory[RI any] struct { + err error +} + +func (f fakeFactory[RI]) NewReportingPlugin(context.Context, ocr3types.ReportingPluginConfig) (ocr3types.ReportingPlugin[RI], ocr3types.ReportingPluginInfo, error) { + if f.err != nil { + return nil, ocr3types.ReportingPluginInfo{}, f.err + } + return fakePlugin[RI]{}, ocr3types.ReportingPluginInfo{}, nil +} diff --git a/core/services/ocr3/promwrapper/plugin.go b/core/services/ocr3/promwrapper/plugin.go new file mode 100644 index 00000000000..dcee5050d1e --- /dev/null +++ b/core/services/ocr3/promwrapper/plugin.go @@ -0,0 +1,138 @@ +package promwrapper + +import ( + "context" + "strconv" + "time" + + "github.com/prometheus/client_golang/prometheus" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) + +var _ ocr3types.ReportingPlugin[any] = &reportingPlugin[any]{} + +type reportingPlugin[RI any] struct { + ocr3types.ReportingPlugin[RI] + chainID string + plugin string + configDigest string + + // Prometheus components for tracking metrics + reportsGenerated *prometheus.CounterVec + durations *prometheus.HistogramVec + status *prometheus.GaugeVec +} + +func newReportingPlugin[RI any]( + origin ocr3types.ReportingPlugin[RI], + chainID string, + plugin string, + configDigest string, + reportsGenerated *prometheus.CounterVec, + durations *prometheus.HistogramVec, + status *prometheus.GaugeVec, +) *reportingPlugin[RI] { + return &reportingPlugin[RI]{ + ReportingPlugin: origin, + chainID: chainID, + plugin: plugin, + configDigest: configDigest, + reportsGenerated: reportsGenerated, + durations: durations, + status: status, + } +} + +func (p *reportingPlugin[RI]) Query(ctx context.Context, outctx ocr3types.OutcomeContext) (ocrtypes.Query, error) { + return withObservedExecution(p, query, func() (ocrtypes.Query, error) { + return p.ReportingPlugin.Query(ctx, outctx) + }) +} + +func (p *reportingPlugin[RI]) Observation(ctx context.Context, outctx ocr3types.OutcomeContext, query ocrtypes.Query) (ocrtypes.Observation, error) { + return withObservedExecution(p, observation, func() (ocrtypes.Observation, error) { + return p.ReportingPlugin.Observation(ctx, outctx, query) + }) +} + +func (p *reportingPlugin[RI]) ValidateObservation(ctx context.Context, outctx ocr3types.OutcomeContext, query ocrtypes.Query, ao ocrtypes.AttributedObservation) error { + _, err := withObservedExecution(p, validateObservation, func() (any, error) { + err := p.ReportingPlugin.ValidateObservation(ctx, outctx, query, ao) + return nil, err + }) + return err +} + +func (p *reportingPlugin[RI]) Outcome(ctx context.Context, outctx ocr3types.OutcomeContext, query ocrtypes.Query, aos []ocrtypes.AttributedObservation) (ocr3types.Outcome, error) { + return withObservedExecution(p, outcome, func() (ocr3types.Outcome, error) { + return p.ReportingPlugin.Outcome(ctx, outctx, query, aos) + }) +} + +func (p *reportingPlugin[RI]) Reports(ctx context.Context, seqNr uint64, outcome ocr3types.Outcome) ([]ocr3types.ReportPlus[RI], error) { + result, err := withObservedExecution(p, reports, func() ([]ocr3types.ReportPlus[RI], error) { + return p.ReportingPlugin.Reports(ctx, seqNr, outcome) + }) + p.trackReports(reports, len(result)) + return result, err +} + +func (p *reportingPlugin[RI]) ShouldAcceptAttestedReport(ctx context.Context, seqNr uint64, reportWithInfo ocr3types.ReportWithInfo[RI]) (bool, error) { + result, err := withObservedExecution(p, shouldAccept, func() (bool, error) { + return p.ReportingPlugin.ShouldAcceptAttestedReport(ctx, seqNr, reportWithInfo) + }) + p.trackReports(shouldAccept, boolToInt(result)) + return result, err +} + +func (p *reportingPlugin[RI]) ShouldTransmitAcceptedReport(ctx context.Context, seqNr uint64, reportWithInfo ocr3types.ReportWithInfo[RI]) (bool, error) { + result, err := withObservedExecution(p, shouldTransmit, func() (bool, error) { + return p.ReportingPlugin.ShouldTransmitAcceptedReport(ctx, seqNr, reportWithInfo) + }) + p.trackReports(shouldTransmit, boolToInt(result)) + return result, err +} + +func (p *reportingPlugin[RI]) Close() error { + p.updateStatus(false) + return p.ReportingPlugin.Close() +} + +func (p *reportingPlugin[RI]) trackReports(function functionType, count int) { + p.reportsGenerated. + WithLabelValues(p.chainID, p.plugin, string(function)). + Add(float64(count)) +} + +func (p *reportingPlugin[RI]) updateStatus(status bool) { + p.status. + WithLabelValues(p.chainID, p.plugin, p.configDigest). + Set(float64(boolToInt(status))) +} + +func boolToInt(arg bool) int { + if arg { + return 1 + } + return 0 +} + +func withObservedExecution[RI, R any]( + p *reportingPlugin[RI], + function functionType, + exec func() (R, error), +) (R, error) { + start := time.Now() + result, err := exec() + + success := err == nil + + p.durations. + WithLabelValues(p.chainID, p.plugin, string(function), strconv.FormatBool(success)). + Observe(float64(time.Since(start))) + + p.updateStatus(true) + + return result, err +} diff --git a/core/services/ocr3/promwrapper/plugin_test.go b/core/services/ocr3/promwrapper/plugin_test.go new file mode 100644 index 00000000000..9a7b6f2e648 --- /dev/null +++ b/core/services/ocr3/promwrapper/plugin_test.go @@ -0,0 +1,178 @@ +package promwrapper + +import ( + "context" + "errors" + "testing" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/testutil" + io_prometheus_client "github.com/prometheus/client_model/go" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) + +func Test_ReportsGeneratedGauge(t *testing.T) { + plugin1 := newReportingPlugin( + fakePlugin[uint]{reports: make([]ocr3types.ReportPlus[uint], 2)}, + "123", "empty", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3PluginStatus, + ) + plugin2 := newReportingPlugin( + fakePlugin[bool]{reports: make([]ocr3types.ReportPlus[bool], 10)}, + "solana", "different_plugin", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3PluginStatus, + ) + plugin3 := newReportingPlugin( + fakePlugin[string]{err: errors.New("error")}, + "1234", "empty", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3PluginStatus, + ) + + r1, err := plugin1.Reports(tests.Context(t), 1, nil) + require.NoError(t, err) + require.Len(t, r1, 2) + + for i := 0; i < 10; i++ { + r2, err1 := plugin2.Reports(tests.Context(t), 1, nil) + require.NoError(t, err1) + require.Len(t, r2, 10) + } + + _, err = plugin2.ShouldAcceptAttestedReport(tests.Context(t), 1, ocr3types.ReportWithInfo[bool]{}) + require.NoError(t, err) + + _, err = plugin3.Reports(tests.Context(t), 1, nil) + require.Error(t, err) + + g1 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("123", "empty", "reports")) + require.Equal(t, 2, int(g1)) + + g2 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("solana", "different_plugin", "reports")) + require.Equal(t, 100, int(g2)) + + g3 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("solana", "different_plugin", "shouldAccept")) + require.Equal(t, 1, int(g3)) + + g4 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("1234", "empty", "reports")) + require.Equal(t, 0, int(g4)) + + pluginHealth := testutil.ToFloat64(promOCR3PluginStatus.WithLabelValues("123", "empty", "abc")) + require.Equal(t, 1, int(pluginHealth)) + + require.NoError(t, plugin1.Close()) + pluginHealth = testutil.ToFloat64(promOCR3PluginStatus.WithLabelValues("123", "empty", "abc")) + require.Equal(t, 0, int(pluginHealth)) +} + +func Test_DurationHistograms(t *testing.T) { + plugin1 := newReportingPlugin( + fakePlugin[uint]{}, + "123", "empty", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3PluginStatus, + ) + plugin2 := newReportingPlugin( + fakePlugin[uint]{err: errors.New("error")}, + "123", "empty", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3PluginStatus, + ) + plugin3 := newReportingPlugin( + fakePlugin[uint]{}, + "solana", "commit", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3PluginStatus, + ) + + for _, p := range []*reportingPlugin[uint]{plugin1, plugin2, plugin3} { + _, _ = p.Query(tests.Context(t), ocr3types.OutcomeContext{}) + for i := 0; i < 2; i++ { + _, _ = p.Observation(tests.Context(t), ocr3types.OutcomeContext{}, nil) + } + _ = p.ValidateObservation(tests.Context(t), ocr3types.OutcomeContext{}, nil, ocrtypes.AttributedObservation{}) + _, _ = p.Outcome(tests.Context(t), ocr3types.OutcomeContext{}, nil, nil) + _, _ = p.Reports(tests.Context(t), 0, nil) + _, _ = p.ShouldAcceptAttestedReport(tests.Context(t), 0, ocr3types.ReportWithInfo[uint]{}) + _, _ = p.ShouldTransmitAcceptedReport(tests.Context(t), 0, ocr3types.ReportWithInfo[uint]{}) + } + + require.Equal(t, 1, counterFromHistogramByLabels(t, promOCR3Durations, "123", "empty", "query", "true")) + require.Equal(t, 1, counterFromHistogramByLabels(t, promOCR3Durations, "123", "empty", "query", "false")) + require.Equal(t, 1, counterFromHistogramByLabels(t, promOCR3Durations, "solana", "commit", "query", "true")) + + require.Equal(t, 2, counterFromHistogramByLabels(t, promOCR3Durations, "123", "empty", "observation", "true")) + require.Equal(t, 2, counterFromHistogramByLabels(t, promOCR3Durations, "123", "empty", "observation", "false")) + require.Equal(t, 2, counterFromHistogramByLabels(t, promOCR3Durations, "solana", "commit", "observation", "true")) +} + +type fakePlugin[RI any] struct { + reports []ocr3types.ReportPlus[RI] + err error +} + +func (f fakePlugin[RI]) Query(context.Context, ocr3types.OutcomeContext) (ocrtypes.Query, error) { + if f.err != nil { + return nil, f.err + } + return ocrtypes.Query{}, nil +} + +func (f fakePlugin[RI]) Observation(context.Context, ocr3types.OutcomeContext, ocrtypes.Query) (ocrtypes.Observation, error) { + if f.err != nil { + return nil, f.err + } + return ocrtypes.Observation{}, nil +} + +func (f fakePlugin[RI]) ValidateObservation(context.Context, ocr3types.OutcomeContext, ocrtypes.Query, ocrtypes.AttributedObservation) error { + return f.err +} + +func (f fakePlugin[RI]) ObservationQuorum(context.Context, ocr3types.OutcomeContext, ocrtypes.Query, []ocrtypes.AttributedObservation) (quorumReached bool, err error) { + return false, f.err +} + +func (f fakePlugin[RI]) Outcome(context.Context, ocr3types.OutcomeContext, ocrtypes.Query, []ocrtypes.AttributedObservation) (ocr3types.Outcome, error) { + if f.err != nil { + return nil, f.err + } + return ocr3types.Outcome{}, nil +} + +func (f fakePlugin[RI]) Reports(context.Context, uint64, ocr3types.Outcome) ([]ocr3types.ReportPlus[RI], error) { + if f.err != nil { + return nil, f.err + } + return f.reports, nil +} + +func (f fakePlugin[RI]) ShouldAcceptAttestedReport(context.Context, uint64, ocr3types.ReportWithInfo[RI]) (bool, error) { + if f.err != nil { + return false, f.err + } + return true, nil +} + +func (f fakePlugin[RI]) ShouldTransmitAcceptedReport(context.Context, uint64, ocr3types.ReportWithInfo[RI]) (bool, error) { + if f.err != nil { + return false, f.err + } + return true, nil +} + +func (f fakePlugin[RI]) Close() error { + return f.err +} + +func counterFromHistogramByLabels(t *testing.T, histogramVec *prometheus.HistogramVec, labels ...string) int { + observer, err := histogramVec.GetMetricWithLabelValues(labels...) + require.NoError(t, err) + + metricCh := make(chan prometheus.Metric, 1) + observer.(prometheus.Histogram).Collect(metricCh) + close(metricCh) + + metric := <-metricCh + pb := &io_prometheus_client.Metric{} + err = metric.Write(pb) + require.NoError(t, err) + + //nolint:gosec // we don't care about that in tests + return int(pb.GetHistogram().GetSampleCount()) +} diff --git a/core/services/ocr3/promwrapper/types.go b/core/services/ocr3/promwrapper/types.go new file mode 100644 index 00000000000..2fa29dcdf20 --- /dev/null +++ b/core/services/ocr3/promwrapper/types.go @@ -0,0 +1,58 @@ +package promwrapper + +import ( + "time" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" +) + +type functionType string + +const ( + query functionType = "query" + observation functionType = "observation" + validateObservation functionType = "validateObservation" + outcome functionType = "outcome" + reports functionType = "reports" + shouldAccept functionType = "shouldAccept" + shouldTransmit functionType = "shouldTransmit" +) + +var ( + buckets = []float64{ + float64(10 * time.Millisecond), + float64(50 * time.Millisecond), + float64(100 * time.Millisecond), + float64(200 * time.Millisecond), + float64(500 * time.Millisecond), + float64(700 * time.Millisecond), + float64(time.Second), + float64(2 * time.Second), + float64(5 * time.Second), + float64(10 * time.Second), + } + + promOCR3ReportsGenerated = promauto.NewCounterVec( + prometheus.CounterOpts{ + Name: "ocr3_reporting_plugin_reports_processed", + Help: "Tracks number of reports processed/generated within by different OCR3 functions", + }, + []string{"chainID", "plugin", "function"}, + ) + promOCR3Durations = promauto.NewHistogramVec( + prometheus.HistogramOpts{ + Name: "ocr3_reporting_plugin_duration", + Help: "The amount of time elapsed during the OCR3 plugin's function", + Buckets: buckets, + }, + []string{"chainID", "plugin", "function", "success"}, + ) + promOCR3PluginStatus = promauto.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "ocr3_reporting_plugin_status", + Help: "Gauge indicating whether plugin is up and running or not", + }, + []string{"chainID", "plugin", "configDigest"}, + ) +) diff --git a/core/services/ocrcommon/adapters.go b/core/services/ocrcommon/adapters.go index 33e4971bc82..c27a276669b 100644 --- a/core/services/ocrcommon/adapters.go +++ b/core/services/ocrcommon/adapters.go @@ -112,7 +112,7 @@ func MarshalMultichainPublicKey(ost map[string]ocrtypes.OnchainPublicKey) (ocrty if length < 0 || length > math.MaxUint16 { return nil, fmt.Errorf("pubKey doesn't fit into uint16") } - if err = binary.Write(buf, binary.LittleEndian, uint16(length)); err != nil { //nolint:gosec + if err = binary.Write(buf, binary.LittleEndian, uint16(length)); err != nil { return nil, err } _, _ = buf.Write(pubKey) diff --git a/core/services/relay/dummy/relayer.go b/core/services/relay/dummy/relayer.go index 3275272b46f..ba65d10e911 100644 --- a/core/services/relay/dummy/relayer.go +++ b/core/services/relay/dummy/relayer.go @@ -31,7 +31,7 @@ func NewRelayer(lggr logger.Logger, chainID string) loop.Relayer { return &relayer{lggr, chainID} } -func (r *relayer) NewChainWriter(ctx context.Context, chainWriterConfig []byte) (types.ChainWriter, error) { +func (r *relayer) NewContractWriter(ctx context.Context, chainWriterConfig []byte) (types.ContractWriter, error) { return nil, nil } diff --git a/core/services/relay/evm/bindings/chain_reader_tester.go b/core/services/relay/evm/bindings/chain_reader_tester.go index f15f1431679..e5299b0d59a 100644 --- a/core/services/relay/evm/bindings/chain_reader_tester.go +++ b/core/services/relay/evm/bindings/chain_reader_tester.go @@ -13,7 +13,7 @@ import ( type ChainReaderTester struct { BoundContract types.BoundContract ContractReader types.ContractReader - ChainWriter types.ChainWriter + ChainWriter types.ContractWriter } type AccountStruct struct { diff --git a/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go b/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go index ba29e98526e..3bcf8164a7b 100644 --- a/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go +++ b/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go @@ -5,12 +5,16 @@ import ( "crypto/rand" "encoding/hex" "encoding/json" + "fmt" "testing" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/jonboulle/clockwork" + "github.com/stretchr/testify/assert" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/custmsg" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -18,6 +22,7 @@ import ( coretestutils "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/capabilities/testutils" evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" "github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer" @@ -26,6 +31,109 @@ import ( "github.com/stretchr/testify/require" ) +type testEvtHandler struct { + events []syncer.Event +} + +func (m *testEvtHandler) Handle(ctx context.Context, event syncer.Event) error { + m.events = append(m.events, event) + return nil +} + +func newTestEvtHandler() *testEvtHandler { + return &testEvtHandler{ + events: make([]syncer.Event, 0), + } +} + +type testWorkflowRegistryContractLoader struct { +} + +type testDonNotifier struct { + don capabilities.DON + err error +} + +func (t *testDonNotifier) WaitForDon(ctx context.Context) (capabilities.DON, error) { + return t.don, t.err +} + +func (m *testWorkflowRegistryContractLoader) LoadWorkflows(ctx context.Context, don capabilities.DON) (*types.Head, error) { + return &types.Head{ + Height: "0", + Hash: nil, + Timestamp: 0, + }, nil +} + +func Test_InitialStateSync(t *testing.T) { + lggr := logger.TestLogger(t) + backendTH := testutils.NewEVMBackendTH(t) + donID := uint32(1) + + // Deploy a test workflow_registry + wfRegistryAddr, _, wfRegistryC, err := workflow_registry_wrapper.DeployWorkflowRegistry(backendTH.ContractsOwner, backendTH.Backend.Client()) + backendTH.Backend.Commit() + require.NoError(t, err) + + // setup contract state to allow the secrets to be updated + updateAllowedDONs(t, backendTH, wfRegistryC, []uint32{donID}, true) + updateAuthorizedAddress(t, backendTH, wfRegistryC, []common.Address{backendTH.ContractsOwner.From}, true) + + // The number of workflows should be greater than the workflow registry contracts pagination limit to ensure + // that the syncer will query the contract multiple times to get the full list of workflows + numberWorkflows := 250 + for i := 0; i < numberWorkflows; i++ { + var workflowID [32]byte + _, err = rand.Read((workflowID)[:]) + require.NoError(t, err) + workflow := RegisterWorkflowCMD{ + Name: fmt.Sprintf("test-wf-%d", i), + DonID: donID, + Status: uint8(1), + SecretsURL: "someurl", + } + workflow.ID = workflowID + registerWorkflow(t, backendTH, wfRegistryC, workflow) + } + + testEventHandler := newTestEvtHandler() + loader := syncer.NewWorkflowRegistryContractLoader(lggr, wfRegistryAddr.Hex(), func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { + return backendTH.NewContractReader(ctx, t, bytes) + }, testEventHandler) + + // Create the worker + worker := syncer.NewWorkflowRegistry( + lggr, + func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { + return backendTH.NewContractReader(ctx, t, bytes) + }, + wfRegistryAddr.Hex(), + syncer.WorkflowEventPollerConfig{ + QueryCount: 20, + }, + testEventHandler, + loader, + &testDonNotifier{ + don: capabilities.DON{ + ID: donID, + }, + err: nil, + }, + syncer.WithTicker(make(chan time.Time)), + ) + + servicetest.Run(t, worker) + + require.Eventually(t, func() bool { + return len(testEventHandler.events) == numberWorkflows + }, 5*time.Second, time.Second) + + for _, event := range testEventHandler.events { + assert.Equal(t, syncer.WorkflowRegisteredEvent, event.GetEventType()) + } +} + func Test_SecretsWorker(t *testing.T) { var ( ctx = coretestutils.Context(t) @@ -49,7 +157,7 @@ func Test_SecretsWorker(t *testing.T) { fetcherFn = func(_ context.Context, _ string) ([]byte, error) { return []byte(wantContents), nil } - contractName = syncer.ContractName + contractName = syncer.WorkflowRegistryContractName forceUpdateSecretsEvent = string(syncer.ForceUpdateSecretsEvent) ) @@ -81,6 +189,9 @@ func Test_SecretsWorker(t *testing.T) { ChainSpecificName: forceUpdateSecretsEvent, ReadType: evmtypes.Event, }, + syncer.GetWorkflowMetadataListByDONMethodName: { + ChainSpecificName: syncer.GetWorkflowMetadataListByDONMethodName, + }, }, }, }, @@ -112,26 +223,28 @@ func Test_SecretsWorker(t *testing.T) { require.NoError(t, err) require.Equal(t, contents, giveContents) - // Create the worker - worker := syncer.NewWorkflowRegistry( - lggr, - orm, - contractReader, - fetcherFn, - wfRegistryAddr.Hex(), - nil, - nil, - emitter, - syncer.WithTicker(giveTicker.C), - ) + handler := syncer.NewEventHandler(lggr, orm, fetcherFn, nil, nil, + emitter, clockwork.NewFakeClock(), workflowkey.Key{}) - servicetest.Run(t, worker) + worker := syncer.NewWorkflowRegistry(lggr, func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { + return contractReader, nil + }, wfRegistryAddr.Hex(), + syncer.WorkflowEventPollerConfig{ + QueryCount: 20, + }, handler, &testWorkflowRegistryContractLoader{}, &testDonNotifier{ + don: capabilities.DON{ + ID: donID, + }, + err: nil, + }, syncer.WithTicker(giveTicker.C)) // setup contract state to allow the secrets to be updated updateAllowedDONs(t, backendTH, wfRegistryC, []uint32{donID}, true) updateAuthorizedAddress(t, backendTH, wfRegistryC, []common.Address{backendTH.ContractsOwner.From}, true) registerWorkflow(t, backendTH, wfRegistryC, giveWorkflow) + servicetest.Run(t, worker) + // generate a log event requestForceUpdateSecrets(t, backendTH, wfRegistryC, giveSecretsURL) @@ -141,7 +254,7 @@ func Test_SecretsWorker(t *testing.T) { lggr.Debugf("got secrets %v", secrets) require.NoError(t, err) return secrets == wantContents - }, 5*time.Second, time.Second) + }, 15*time.Second, time.Second) } func updateAuthorizedAddress( diff --git a/core/services/relay/evm/chain_components_test.go b/core/services/relay/evm/chain_components_test.go index 3efa50d1ec5..bc2703d9678 100644 --- a/core/services/relay/evm/chain_components_test.go +++ b/core/services/relay/evm/chain_components_test.go @@ -22,6 +22,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" @@ -35,8 +36,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - . "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/evmtesting" //nolint common practice to import test mods with . "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + + . "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/evmtesting" //nolint:revive // dot-imports ) const commonGasLimitOnEvms = uint64(4712388) @@ -205,8 +207,11 @@ func TestContractReaderEventsInitValidation(t *testing.T) { } func TestChainComponents(t *testing.T) { + testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/BCFR-1083") t.Parallel() it := &EVMChainComponentsInterfaceTester[*testing.T]{Helper: &helper{}} + // TODO, generated binding tests are broken + it.DisableTests([]string{interfacetests.ContractReaderGetLatestValue}) it.Init(t) // add new subtests here so that it can be run on real chains too @@ -309,7 +314,7 @@ func (h *helper) ChainReaderEVMClient(ctx context.Context, t *testing.T, ht logp return cwh } -func (h *helper) WrappedChainWriter(cw clcommontypes.ChainWriter, client client.Client) clcommontypes.ChainWriter { +func (h *helper) WrappedChainWriter(cw clcommontypes.ContractWriter, client client.Client) clcommontypes.ContractWriter { cwhw := evm.NewChainWriterHistoricalWrapper(cw, client.(*evm.ClientWithContractHistory)) return cwhw } diff --git a/core/services/relay/evm/chain_reader_historical_client_wrapper_test.go b/core/services/relay/evm/chain_reader_historical_client_wrapper_test.go index d0aa4a21332..31122c8a5c4 100644 --- a/core/services/relay/evm/chain_reader_historical_client_wrapper_test.go +++ b/core/services/relay/evm/chain_reader_historical_client_wrapper_test.go @@ -13,12 +13,13 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + + . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint:revive // dot-imports ) // ClientWithContractHistory makes it possible to modify client.Client CallContract so that it returns historical data. diff --git a/core/services/relay/evm/chain_writer.go b/core/services/relay/evm/chain_writer.go index 779a13de90c..ab82a67084c 100644 --- a/core/services/relay/evm/chain_writer.go +++ b/core/services/relay/evm/chain_writer.go @@ -26,7 +26,7 @@ import ( type ChainWriterService interface { services.ServiceCtx - commontypes.ChainWriter + commontypes.ContractWriter } // Compile-time assertion that chainWriter implements the ChainWriterService interface. diff --git a/core/services/relay/evm/chain_writer_historical_wrapper_test.go b/core/services/relay/evm/chain_writer_historical_wrapper_test.go index 233d7bc2e2f..3e661b553e2 100644 --- a/core/services/relay/evm/chain_writer_historical_wrapper_test.go +++ b/core/services/relay/evm/chain_writer_historical_wrapper_test.go @@ -2,7 +2,6 @@ package evm import ( "context" - "math/big" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -15,12 +14,12 @@ import ( // Since the geth simulated backend doesn't support historical data, we use this // thin wrapper. type ChainWriterHistoricalWrapper struct { - commontypes.ChainWriter + commontypes.ContractWriter cwh *ClientWithContractHistory } -func NewChainWriterHistoricalWrapper(cw commontypes.ChainWriter, cwh *ClientWithContractHistory) *ChainWriterHistoricalWrapper { - return &ChainWriterHistoricalWrapper{ChainWriter: cw, cwh: cwh} +func NewChainWriterHistoricalWrapper(cw commontypes.ContractWriter, cwh *ClientWithContractHistory) *ChainWriterHistoricalWrapper { + return &ChainWriterHistoricalWrapper{ContractWriter: cw, cwh: cwh} } func (cwhw *ChainWriterHistoricalWrapper) SubmitTransaction(ctx context.Context, contractName, method string, args any, transactionID string, toAddress string, meta *commontypes.TxMeta, value *big.Int) error { @@ -38,7 +37,7 @@ func (cwhw *ChainWriterHistoricalWrapper) SubmitTransaction(ctx context.Context, return err } } - return cwhw.ChainWriter.SubmitTransaction(ctx, contractName, method, args, transactionID, toAddress, meta, value) + return cwhw.ContractWriter.SubmitTransaction(ctx, contractName, method, args, transactionID, toAddress, meta, value) } func (cwhw *ChainWriterHistoricalWrapper) getPrimitiveValueIfPossible(args any) (bool, uint64) { diff --git a/core/services/relay/evm/codec/codec_test.go b/core/services/relay/evm/codec/codec_test.go index 2da88abaac1..66fc45a3037 100644 --- a/core/services/relay/evm/codec/codec_test.go +++ b/core/services/relay/evm/codec/codec_test.go @@ -16,14 +16,15 @@ import ( commoncodec "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/evmtesting" - looptestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" //nolint common practice to import test mods with . + looptestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_reader_tester" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + + . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint:revive // dot-imports ) const anyExtraValue = 3 @@ -288,8 +289,8 @@ func packArgs(t *testing.T, allArgs []any, oargs abi.Arguments, request *EncodeR } if request.MissingField { - args = args[1:] //nolint we know it's non-zero len - allArgs = allArgs[1:] //nolint we know it's non-zero len + args = args[1:] + allArgs = allArgs[1:] } bytes, err := args.Pack(allArgs...) diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 1a4af826046..e60dbe1bfdb 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -12,6 +12,7 @@ import ( "net/http" "strings" "sync" + "time" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" @@ -87,7 +88,7 @@ func init() { } } -var _ commontypes.Relayer = &Relayer{} //nolint:staticcheck +var _ commontypes.Relayer = &Relayer{} // The current PluginProvider interface does not support an error return. This was fine up until CCIP. // CCIP is the first product to introduce the idea of incomplete implementations of a provider based on @@ -259,6 +260,14 @@ func (r *Relayer) Close() error { cs := make([]io.Closer, 0, 2) if r.triggerCapability != nil { cs = append(cs, r.triggerCapability) + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + err := r.capabilitiesRegistry.Remove(ctx, r.triggerCapability.ID) + if err != nil { + return err + } } cs = append(cs, r.chain) return services.MultiCloser(cs).Close() @@ -845,7 +854,7 @@ func generateTransmitterFrom(ctx context.Context, rargs commontypes.RelayArgs, e return transmitter, nil } -func (r *Relayer) NewChainWriter(_ context.Context, config []byte) (commontypes.ChainWriter, error) { +func (r *Relayer) NewContractWriter(_ context.Context, config []byte) (commontypes.ContractWriter, error) { var cfg types.ChainWriterConfig if err := json.Unmarshal(config, &cfg); err != nil { return nil, fmt.Errorf("failed to unmarshall chain writer config err: %s", err) diff --git a/core/services/relay/evm/evmtesting/bindings_test_adapter.go b/core/services/relay/evm/evmtesting/bindings_test_adapter.go index 3dd625266ad..6c391aa0a7f 100644 --- a/core/services/relay/evm/evmtesting/bindings_test_adapter.go +++ b/core/services/relay/evm/evmtesting/bindings_test_adapter.go @@ -146,23 +146,23 @@ func (b bindingClientTester) addDefaultBindings(t *testing.T) { if chainReaderTester == nil { chainReaderTester = &bindings.ChainReaderTester{ BoundContract: binding, - ChainWriter: b.bindingsMapping.chainWriterProxy.ChainWriter, + ChainWriter: b.bindingsMapping.chainWriterProxy.ContractWriter, } b.bindingsMapping.chainReaderTesters[binding.Address] = chainReaderTester } else { - chainReaderTester.ChainWriter = b.bindingsMapping.chainWriterProxy.ChainWriter + chainReaderTester.ChainWriter = b.bindingsMapping.chainWriterProxy.ContractWriter } } } -func (b bindingClientTester) GetChainWriter(t *testing.T) commontypes.ChainWriter { - chainWriter := b.ChainComponentsInterfaceTester.GetChainWriter(t) - if b.bindingsMapping.chainWriterProxy.ChainWriter == nil { +func (b bindingClientTester) GetChainWriter(t *testing.T) commontypes.ContractWriter { + chainWriter := b.ChainComponentsInterfaceTester.GetContractWriter(t) + if b.bindingsMapping.chainWriterProxy.ContractWriter == nil { b.addDefaultBindings(t) for _, tester := range b.bindingsMapping.chainReaderTesters { tester.ChainWriter = chainWriter } - b.bindingsMapping.chainWriterProxy.ChainWriter = chainWriter + b.bindingsMapping.chainWriterProxy.ContractWriter = chainWriter } return b.bindingsMapping.chainWriterProxy } @@ -182,7 +182,7 @@ type bindingContractReaderProxy struct { } type bindingChainWriterProxy struct { - commontypes.ChainWriter + commontypes.ContractWriter bm *bindingsMapping } @@ -192,7 +192,7 @@ func (b bindingContractReaderProxy) Bind(ctx context.Context, boundContracts []c b.bm.chainReaderTesters[updatedBinding.Address] = &bindings.ChainReaderTester{ BoundContract: updatedBinding, ContractReader: b.ContractReader, - ChainWriter: b.bm.chainWriterProxy.ChainWriter, + ChainWriter: b.bm.chainWriterProxy.ContractWriter, } } return b.ContractReader.Bind(ctx, updatedBindings) @@ -258,7 +258,7 @@ func (b bindingChainWriterProxy) SubmitTransaction(ctx context.Context, contract } func (b *bindingChainWriterProxy) GetTransactionStatus(ctx context.Context, transactionID string) (commontypes.TransactionStatus, error) { - return b.ChainWriter.GetTransactionStatus(ctx, transactionID) + return b.ContractWriter.GetTransactionStatus(ctx, transactionID) } func removeAddressFromReadIdentifier(s string) string { diff --git a/core/services/relay/evm/evmtesting/chain_components_interface_tester.go b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go index 9655fb78457..71bd94f0e9f 100644 --- a/core/services/relay/evm/evmtesting/chain_components_interface_tester.go +++ b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go @@ -16,7 +16,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/codec" clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -32,6 +31,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + + . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint:revive // dot-imports ) const ( @@ -56,7 +57,7 @@ type EVMChainComponentsInterfaceTesterHelper[T TestingT[T]] interface { TXM(T, client.Client) evmtxmgr.TxManager // To enable the historical wrappers required for Simulated Backend tests. ChainReaderEVMClient(ctx context.Context, t T, ht logpoller.HeadTracker, conf types.ChainReaderConfig) client.Client - WrappedChainWriter(cw clcommontypes.ChainWriter, client client.Client) clcommontypes.ChainWriter + WrappedChainWriter(cw clcommontypes.ContractWriter, client client.Client) clcommontypes.ContractWriter } type EVMChainComponentsInterfaceTester[T TestingT[T]] struct { @@ -394,7 +395,7 @@ func (it *EVMChainComponentsInterfaceTester[T]) GetContractReader(t T) clcommont func (it *EVMChainComponentsInterfaceTester[T]) GenerateBlocksTillConfidenceLevel(t T, contractName, readName string, confidenceLevel primitives.ConfidenceLevel) { } -func (it *EVMChainComponentsInterfaceTester[T]) GetChainWriter(t T) clcommontypes.ChainWriter { +func (it *EVMChainComponentsInterfaceTester[T]) GetContractWriter(t T) clcommontypes.ContractWriter { ctx := it.Helper.Context(t) if it.cw != nil { return it.cw diff --git a/core/services/relay/evm/evmtesting/run_tests.go b/core/services/relay/evm/evmtesting/run_tests.go index 5f3cdbb2fd7..b6abffdcb2f 100644 --- a/core/services/relay/evm/evmtesting/run_tests.go +++ b/core/services/relay/evm/evmtesting/run_tests.go @@ -18,7 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/read" - . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . + . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint:revive // dot-imports ) const ( diff --git a/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go b/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go index b24e69ce387..f5e2c7453e8 100644 --- a/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go +++ b/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go @@ -157,7 +157,7 @@ func (r *ReportCodec) ValidFromBlockNumFromReport(report ocrtypes.Report) (int64 if n > math.MaxInt64 { return 0, fmt.Errorf("ValidFromBlockNum=%d overflows max int64", n) } - return int64(n), nil //nolint:gosec // G115 + return int64(n), nil } func Test_ReportCodec_ValidFromBlockNumFromReport(t *testing.T) { diff --git a/core/services/relay/evm/write_target.go b/core/services/relay/evm/write_target.go index cd30e8ab3c3..994dbbb77ce 100644 --- a/core/services/relay/evm/write_target.go +++ b/core/services/relay/evm/write_target.go @@ -68,7 +68,7 @@ func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain return nil, fmt.Errorf("failed to marshal chainwriter config: %w", err) } - cw, err := relayer.NewChainWriter(ctx, encodedWriterConfig) + cw, err := relayer.NewContractWriter(ctx, encodedWriterConfig) if err != nil { return nil, err } diff --git a/core/services/relay/relay.go b/core/services/relay/relay.go index 913923a9b2f..0b1293c8d79 100644 --- a/core/services/relay/relay.go +++ b/core/services/relay/relay.go @@ -37,7 +37,7 @@ type ServerAdapter struct { } // NewServerAdapter returns a new ServerAdapter. -func NewServerAdapter(r types.Relayer) *ServerAdapter { //nolint:staticcheck +func NewServerAdapter(r types.Relayer) *ServerAdapter { return &ServerAdapter{Relayer: r} } diff --git a/core/services/workflows/delegate.go b/core/services/workflows/delegate.go index 1db26729ca6..fc8fe3fe840 100644 --- a/core/services/workflows/delegate.go +++ b/core/services/workflows/delegate.go @@ -79,13 +79,22 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser return []job.ServiceCtx{engine}, nil } +type noopSecretsFetcher struct{} + +func (n *noopSecretsFetcher) SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) { + return map[string]string{}, nil +} + +func newNoopSecretsFetcher() *noopSecretsFetcher { + return &noopSecretsFetcher{} +} + func NewDelegate( logger logger.Logger, registry core.CapabilitiesRegistry, - secretsFetcher secretsFetcher, store store.Store, ) *Delegate { - return &Delegate{logger: logger, registry: registry, secretsFetcher: secretsFetcher, store: store} + return &Delegate{logger: logger, registry: registry, secretsFetcher: newNoopSecretsFetcher(), store: store} } func ValidatedWorkflowJobSpec(ctx context.Context, tomlString string) (job.Job, error) { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 69655b5b39c..11d2bdc3480 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -96,7 +96,7 @@ func (sucm *stepUpdateManager) len() int64 { } type secretsFetcher interface { - SecretsFor(ctx context.Context, workflowOwner, workflowName string) (map[string]string, error) + SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) } // Engine handles the lifecycle of a single workflow and its executions. @@ -142,11 +142,7 @@ func (e *Engine) Start(_ context.Context) error { // create a new context, since the one passed in via Start is short-lived. ctx, _ := e.stopCh.NewCtx() - // spin up monitoring resources - err := initMonitoringResources() - if err != nil { - return fmt.Errorf("could not initialize monitoring resources: %w", err) - } + e.metrics.incrementWorkflowInitializationCounter(ctx) e.wg.Add(e.maxWorkerLimit) for i := 0; i < e.maxWorkerLimit; i++ { @@ -358,6 +354,7 @@ func (e *Engine) init(ctx context.Context) { e.logger.Info("engine initialized") logCustMsg(ctx, e.cma, "workflow registered", e.logger) + e.metrics.incrementWorkflowRegisteredCounter(ctx) e.afterInit(true) } @@ -439,7 +436,7 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, trig Metadata: capabilities.RequestMetadata{ WorkflowID: e.workflow.id, WorkflowOwner: e.workflow.owner, - WorkflowName: e.workflow.name, + WorkflowName: e.workflow.hexName, WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, ReferenceID: t.Ref, @@ -678,7 +675,6 @@ func (e *Engine) queueIfReady(state store.WorkflowExecution, step *step) { func (e *Engine) finishExecution(ctx context.Context, cma custmsg.MessageEmitter, executionID string, status string) error { l := e.logger.With(platform.KeyWorkflowExecutionID, executionID, "status", status) - metrics := e.metrics.with("status", status) l.Info("finishing execution") @@ -692,18 +688,28 @@ func (e *Engine) finishExecution(ctx context.Context, cma custmsg.MessageEmitter return err } - executionDuration := execState.FinishedAt.Sub(*execState.CreatedAt).Milliseconds() - e.stepUpdatesChMap.remove(executionID) - metrics.updateTotalWorkflowsGauge(ctx, e.stepUpdatesChMap.len()) - metrics.updateWorkflowExecutionLatencyGauge(ctx, executionDuration) + + executionDuration := int64(execState.FinishedAt.Sub(*execState.CreatedAt).Seconds()) + switch status { + case store.StatusCompleted: + e.metrics.updateWorkflowCompletedDurationHistogram(ctx, executionDuration) + case store.StatusCompletedEarlyExit: + e.metrics.updateWorkflowEarlyExitDurationHistogram(ctx, executionDuration) + case store.StatusErrored: + e.metrics.updateWorkflowErrorDurationHistogram(ctx, executionDuration) + case store.StatusTimeout: + // should expect the same values unless the timeout is adjusted. + // using histogram as it gives count of executions for free + e.metrics.updateWorkflowTimeoutDurationHistogram(ctx, executionDuration) + } if executionDuration > fifteenMinutesMs { - logCustMsg(ctx, cma, fmt.Sprintf("execution duration exceeded 15 minutes: %d", executionDuration), l) - l.Warnf("execution duration exceeded 15 minutes: %d", executionDuration) + logCustMsg(ctx, cma, fmt.Sprintf("execution duration exceeded 15 minutes: %d (seconds)", executionDuration), l) + l.Warnf("execution duration exceeded 15 minutes: %d (seconds)", executionDuration) } - logCustMsg(ctx, cma, fmt.Sprintf("execution duration: %d", executionDuration), l) - l.Infof("execution duration: %d", executionDuration) + logCustMsg(ctx, cma, fmt.Sprintf("execution duration: %d (seconds)", executionDuration), l) + l.Infof("execution duration: %d (seconds)", executionDuration) e.onExecutionFinished(executionID) return nil } @@ -747,6 +753,7 @@ func (e *Engine) worker(ctx context.Context) { if err != nil { e.logger.With(platform.KeyWorkflowExecutionID, executionID).Errorf("failed to start execution: %v", err) logCustMsg(ctx, cma, fmt.Sprintf("failed to start execution: %s", err), e.logger) + e.metrics.with(platform.KeyTriggerID, te.ID).incrementTriggerWorkflowStarterErrorCounter(ctx) } else { e.logger.With(platform.KeyWorkflowExecutionID, executionID).Debug("execution started") logCustMsg(ctx, cma, "execution started", e.logger) @@ -770,10 +777,21 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { Ref: msg.stepRef, } - // TODO ks-462 inputs logCustMsg(ctx, cma, "executing step", l) + stepExecutionStartTime := time.Now() inputs, outputs, err := e.executeStep(ctx, l, msg) + stepExecutionDuration := time.Since(stepExecutionStartTime).Seconds() + + curStepID := "UNSET" + curStep, verr := e.workflow.Vertex(msg.stepRef) + if verr == nil { + curStepID = curStep.ID + } else { + l.Errorf("failed to resolve step in workflow; error %v", verr) + } + e.metrics.with(platform.KeyCapabilityID, curStepID).updateWorkflowStepDurationHistogram(ctx, int64(stepExecutionDuration)) + var stepStatus string switch { case errors.Is(capabilities.ErrStopExecution, err): @@ -850,7 +868,7 @@ func (e *Engine) interpolateEnvVars(config map[string]any, env exec.Env) (*value // registry (for capability-level configuration). It doesn't perform any caching of the config values, since // the two registries perform their own caching. func (e *Engine) configForStep(ctx context.Context, lggr logger.Logger, step *step) (*values.Map, error) { - secrets, err := e.secretsFetcher.SecretsFor(ctx, e.workflow.owner, e.workflow.name) + secrets, err := e.secretsFetcher.SecretsFor(ctx, e.workflow.owner, e.workflow.hexName, e.workflow.id) if err != nil { return nil, fmt.Errorf("failed to fetch secrets: %w", err) } @@ -894,16 +912,16 @@ func (e *Engine) configForStep(ctx context.Context, lggr logger.Logger, step *st // executeStep executes the referenced capability within a step and returns the result. func (e *Engine) executeStep(ctx context.Context, lggr logger.Logger, msg stepRequest) (*values.Map, values.Value, error) { - step, err := e.workflow.Vertex(msg.stepRef) + curStep, err := e.workflow.Vertex(msg.stepRef) if err != nil { return nil, nil, err } var inputs any - if step.Inputs.OutputRef != "" { - inputs = step.Inputs.OutputRef + if curStep.Inputs.OutputRef != "" { + inputs = curStep.Inputs.OutputRef } else { - inputs = step.Inputs.Mapping + inputs = curStep.Inputs.Mapping } i, err := exec.FindAndInterpolateAllKeys(inputs, msg.state) @@ -916,7 +934,7 @@ func (e *Engine) executeStep(ctx context.Context, lggr logger.Logger, msg stepRe return nil, nil, err } - config, err := e.configForStep(ctx, lggr, step) + config, err := e.configForStep(ctx, lggr, curStep) if err != nil { return nil, nil, err } @@ -942,7 +960,7 @@ func (e *Engine) executeStep(ctx context.Context, lggr logger.Logger, msg stepRe WorkflowID: msg.state.WorkflowID, WorkflowExecutionID: msg.state.ExecutionID, WorkflowOwner: e.workflow.owner, - WorkflowName: e.workflow.name, + WorkflowName: e.workflow.hexName, WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, ReferenceID: msg.stepRef, @@ -952,9 +970,10 @@ func (e *Engine) executeStep(ctx context.Context, lggr logger.Logger, msg stepRe stepCtx, cancel := context.WithTimeout(ctx, stepTimeoutDuration) defer cancel() - e.metrics.incrementCapabilityInvocationCounter(stepCtx) - output, err := step.capability.Execute(stepCtx, tr) + e.metrics.with(platform.KeyCapabilityID, curStep.ID).incrementCapabilityInvocationCounter(ctx) + output, err := curStep.capability.Execute(stepCtx, tr) if err != nil { + e.metrics.with(platform.KeyStepRef, msg.stepRef, platform.KeyCapabilityID, curStep.ID).incrementCapabilityFailureCounter(ctx) return inputsMap, nil, err } @@ -967,7 +986,7 @@ func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability, tr WorkflowID: e.workflow.id, WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, - WorkflowName: e.workflow.name, + WorkflowName: e.workflow.hexName, WorkflowOwner: e.workflow.owner, ReferenceID: t.Ref, }, @@ -1074,6 +1093,7 @@ func (e *Engine) isWorkflowFullyProcessed(ctx context.Context, state store.Workf return workflowProcessed, store.StatusCompleted, nil } +// heartbeat runs by default every defaultHeartbeatCadence minutes func (e *Engine) heartbeat(ctx context.Context) { defer e.wg.Done() @@ -1087,6 +1107,7 @@ func (e *Engine) heartbeat(ctx context.Context) { return case <-ticker.C: e.metrics.incrementEngineHeartbeatCounter(ctx) + e.metrics.updateTotalWorkflowsGauge(ctx, e.stepUpdatesChMap.len()) logCustMsg(ctx, e.cma, "engine heartbeat at: "+e.clock.Now().Format(time.RFC3339), e.logger) } } @@ -1153,6 +1174,7 @@ func (e *Engine) Close() error { return err } logCustMsg(ctx, e.cma, "workflow unregistered", e.logger) + e.metrics.incrementWorkflowUnregisteredCounter(ctx) return nil }) } @@ -1249,6 +1271,12 @@ func NewEngine(ctx context.Context, cfg Config) (engine *Engine, err error) { // - that the resulting graph is strongly connected (i.e. no disjointed subgraphs exist) // - etc. + // spin up monitoring resources + em, err := initMonitoringResources() + if err != nil { + return nil, fmt.Errorf("could not initialize monitoring resources: %w", err) + } + cma := custmsg.NewLabeler().With(platform.KeyWorkflowID, cfg.WorkflowID, platform.KeyWorkflowOwner, cfg.WorkflowOwner, platform.KeyWorkflowName, cfg.WorkflowName) workflow, err := Parse(cfg.Workflow) if err != nil { @@ -1258,12 +1286,12 @@ func NewEngine(ctx context.Context, cfg Config) (engine *Engine, err error) { workflow.id = cfg.WorkflowID workflow.owner = cfg.WorkflowOwner - workflow.name = hex.EncodeToString([]byte(cfg.WorkflowName)) + workflow.hexName = hex.EncodeToString([]byte(cfg.WorkflowName)) engine = &Engine{ cma: cma, logger: cfg.Lggr.Named("WorkflowEngine").With("workflowID", cfg.WorkflowID), - metrics: workflowsMetricLabeler{metrics.NewLabeler().With(platform.KeyWorkflowID, cfg.WorkflowID, platform.KeyWorkflowOwner, cfg.WorkflowOwner, platform.KeyWorkflowName, cfg.WorkflowName)}, + metrics: workflowsMetricLabeler{metrics.NewLabeler().With(platform.KeyWorkflowID, cfg.WorkflowID, platform.KeyWorkflowOwner, cfg.WorkflowOwner, platform.KeyWorkflowName, cfg.WorkflowName), *em}, registry: cfg.Registry, workflow: workflow, secretsFetcher: cfg.SecretsFetcher, diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 70216ac8c78..95ac74f0c76 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -153,7 +153,7 @@ func newTestEngineWithYAMLSpec(t *testing.T, reg *coreCap.Registry, spec string, type mockSecretsFetcher struct{} -func (s mockSecretsFetcher) SecretsFor(ctx context.Context, workflowOwner, workflowName string) (map[string]string, error) { +func (s mockSecretsFetcher) SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) { return map[string]string{}, nil } @@ -1606,7 +1606,7 @@ type mockFetcher struct { retval map[string]string } -func (m *mockFetcher) SecretsFor(ctx context.Context, workflowOwner, workflowName string) (map[string]string, error) { +func (m *mockFetcher) SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) { return m.retval, nil } diff --git a/core/services/workflows/models.go b/core/services/workflows/models.go index 0faf66d9883..e5d26a474f6 100644 --- a/core/services/workflows/models.go +++ b/core/services/workflows/models.go @@ -20,9 +20,9 @@ import ( // treated differently due to their nature of being the starting // point of a workflow. type workflow struct { - id string - owner string - name string + id string + owner string + hexName string graph.Graph[string, *step] triggers []*triggerCapability diff --git a/core/services/workflows/monitoring.go b/core/services/workflows/monitoring.go index d498ff354c9..8457dadeb60 100644 --- a/core/services/workflows/monitoring.go +++ b/core/services/workflows/monitoring.go @@ -5,90 +5,255 @@ import ( "fmt" "go.opentelemetry.io/otel/metric" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" "github.com/smartcontractkit/chainlink-common/pkg/beholder" "github.com/smartcontractkit/chainlink-common/pkg/metrics" - localMonitoring "github.com/smartcontractkit/chainlink/v2/core/monitoring" + monutils "github.com/smartcontractkit/chainlink/v2/core/monitoring" ) -var registerTriggerFailureCounter metric.Int64Counter -var workflowsRunningGauge metric.Int64Gauge -var capabilityInvocationCounter metric.Int64Counter -var workflowExecutionLatencyGauge metric.Int64Gauge // ms -var workflowStepErrorCounter metric.Int64Counter -var engineHeartbeatCounter metric.Int64UpDownCounter +// em AKA "engine metrics" is to locally scope these instruments to avoid +// data races in testing +type engineMetrics struct { + registerTriggerFailureCounter metric.Int64Counter + triggerWorkflowStarterErrorCounter metric.Int64Counter + workflowsRunningGauge metric.Int64Gauge + capabilityInvocationCounter metric.Int64Counter + capabilityFailureCounter metric.Int64Counter + workflowRegisteredCounter metric.Int64Counter + workflowUnregisteredCounter metric.Int64Counter + workflowExecutionLatencyGauge metric.Int64Gauge // ms + workflowStepErrorCounter metric.Int64Counter + workflowInitializationCounter metric.Int64Counter + engineHeartbeatCounter metric.Int64Counter + workflowCompletedDurationSeconds metric.Int64Histogram + workflowEarlyExitDurationSeconds metric.Int64Histogram + workflowErrorDurationSeconds metric.Int64Histogram + workflowTimeoutDurationSeconds metric.Int64Histogram + workflowStepDurationSeconds metric.Int64Histogram +} + +func initMonitoringResources() (em *engineMetrics, err error) { + em = &engineMetrics{} + em.registerTriggerFailureCounter, err = beholder.GetMeter().Int64Counter("platform_engine_registertrigger_failures") + if err != nil { + return nil, fmt.Errorf("failed to register trigger failure counter: %w", err) + } + + em.triggerWorkflowStarterErrorCounter, err = beholder.GetMeter().Int64Counter("platform_engine_triggerworkflow_starter_errors") + if err != nil { + return nil, fmt.Errorf("failed to register trigger workflow starter error counter: %w", err) + } + + em.workflowsRunningGauge, err = beholder.GetMeter().Int64Gauge("platform_engine_workflow_count") + if err != nil { + return nil, fmt.Errorf("failed to register workflows running gauge: %w", err) + } + + em.capabilityInvocationCounter, err = beholder.GetMeter().Int64Counter("platform_engine_capabilities_count") + if err != nil { + return nil, fmt.Errorf("failed to register capability invocation counter: %w", err) + } + + em.capabilityFailureCounter, err = beholder.GetMeter().Int64Counter("platform_engine_capabilities_failures") + if err != nil { + return nil, fmt.Errorf("failed to register capability failure counter: %w", err) + } + + em.workflowRegisteredCounter, err = beholder.GetMeter().Int64Counter("platform_engine_workflow_registered_count") + if err != nil { + return nil, fmt.Errorf("failed to register workflow registered counter: %w", err) + } + + em.workflowUnregisteredCounter, err = beholder.GetMeter().Int64Counter("platform_engine_workflow_unregistered_count") + if err != nil { + return nil, fmt.Errorf("failed to register workflow unregistered counter: %w", err) + } + + em.workflowExecutionLatencyGauge, err = beholder.GetMeter().Int64Gauge( + "platform_engine_workflow_time", + metric.WithUnit("ms")) + if err != nil { + return nil, fmt.Errorf("failed to register workflow execution latency gauge: %w", err) + } + + em.workflowInitializationCounter, err = beholder.GetMeter().Int64Counter("platform_engine_workflow_initializations") + if err != nil { + return nil, fmt.Errorf("failed to register workflow initialization counter: %w", err) + } + + em.workflowStepErrorCounter, err = beholder.GetMeter().Int64Counter("platform_engine_workflow_errors") + if err != nil { + return nil, fmt.Errorf("failed to register workflow step error counter: %w", err) + } -func initMonitoringResources() (err error) { - registerTriggerFailureCounter, err = beholder.GetMeter().Int64Counter("platform_engine_registertrigger_failures") + em.engineHeartbeatCounter, err = beholder.GetMeter().Int64Counter("platform_engine_heartbeat") if err != nil { - return fmt.Errorf("failed to register trigger failure counter: %w", err) + return nil, fmt.Errorf("failed to register engine heartbeat counter: %w", err) } - workflowsRunningGauge, err = beholder.GetMeter().Int64Gauge("platform_engine_workflow_count") + em.workflowCompletedDurationSeconds, err = beholder.GetMeter().Int64Histogram( + "platform_engine_workflow_completed_time_seconds", + metric.WithDescription("Distribution of completed execution latencies"), + metric.WithUnit("seconds")) if err != nil { - return fmt.Errorf("failed to register workflows running gauge: %w", err) + return nil, fmt.Errorf("failed to register completed duration histogram: %w", err) } - capabilityInvocationCounter, err = beholder.GetMeter().Int64Counter("platform_engine_capabilities_count") + em.workflowEarlyExitDurationSeconds, err = beholder.GetMeter().Int64Histogram( + "platform_engine_workflow_earlyexit_time_seconds", + metric.WithDescription("Distribution of earlyexit execution latencies"), + metric.WithUnit("seconds")) if err != nil { - return fmt.Errorf("failed to register capability invocation counter: %w", err) + return nil, fmt.Errorf("failed to register early exit duration histogram: %w", err) } - workflowExecutionLatencyGauge, err = beholder.GetMeter().Int64Gauge("platform_engine_workflow_time") + em.workflowErrorDurationSeconds, err = beholder.GetMeter().Int64Histogram( + "platform_engine_workflow_error_time_seconds", + metric.WithDescription("Distribution of error execution latencies"), + metric.WithUnit("seconds")) if err != nil { - return fmt.Errorf("failed to register workflow execution latency gauge: %w", err) + return nil, fmt.Errorf("failed to register error duration histogram: %w", err) } - workflowStepErrorCounter, err = beholder.GetMeter().Int64Counter("platform_engine_workflow_errors") + em.workflowTimeoutDurationSeconds, err = beholder.GetMeter().Int64Histogram( + "platform_engine_workflow_timeout_time_seconds", + metric.WithDescription("Distribution of timeout execution latencies"), + metric.WithUnit("seconds")) if err != nil { - return fmt.Errorf("failed to register workflow step error counter: %w", err) + return nil, fmt.Errorf("failed to register timeout duration histogram: %w", err) } - engineHeartbeatCounter, err = beholder.GetMeter().Int64UpDownCounter("platform_engine_heartbeat") + em.workflowStepDurationSeconds, err = beholder.GetMeter().Int64Histogram( + "platform_engine_workflow_step_time_seconds", + metric.WithDescription("Distribution of step execution times"), + metric.WithUnit("seconds")) if err != nil { - return fmt.Errorf("failed to register engine heartbeat counter: %w", err) + return nil, fmt.Errorf("failed to register step execution time histogram: %w", err) } - return nil + return em, nil +} + +// Note: due to the OTEL specification, all histogram buckets +// Must be defined when the beholder client is created +func MetricViews() []sdkmetric.View { + return []sdkmetric.View{ + sdkmetric.NewView( + sdkmetric.Instrument{Name: "platform_engine_workflow_earlyexit_time_seconds"}, + sdkmetric.Stream{Aggregation: sdkmetric.AggregationExplicitBucketHistogram{ + Boundaries: []float64{0, 1, 10, 100}, + }}, + ), + sdkmetric.NewView( + sdkmetric.Instrument{Name: "platform_engine_workflow_completed_time_seconds"}, + sdkmetric.Stream{Aggregation: sdkmetric.AggregationExplicitBucketHistogram{ + Boundaries: []float64{0, 100, 1000, 10_000, 50_000, 100_0000, 500_000}, + }}, + ), + sdkmetric.NewView( + sdkmetric.Instrument{Name: "platform_engine_workflow_error_time_seconds"}, + sdkmetric.Stream{Aggregation: sdkmetric.AggregationExplicitBucketHistogram{ + Boundaries: []float64{0, 20, 60, 120, 240}, + }}, + ), + sdkmetric.NewView( + sdkmetric.Instrument{Name: "platform_engine_workflow_step_time_seconds"}, + sdkmetric.Stream{Aggregation: sdkmetric.AggregationExplicitBucketHistogram{ + Boundaries: []float64{0, 20, 60, 120, 240}, + }}, + ), + } } // workflowsMetricLabeler wraps monitoring.MetricsLabeler to provide workflow specific utilities // for monitoring resources type workflowsMetricLabeler struct { metrics.Labeler + em engineMetrics } func (c workflowsMetricLabeler) with(keyValues ...string) workflowsMetricLabeler { - return workflowsMetricLabeler{c.With(keyValues...)} + return workflowsMetricLabeler{c.With(keyValues...), c.em} } func (c workflowsMetricLabeler) incrementRegisterTriggerFailureCounter(ctx context.Context) { - otelLabels := localMonitoring.KvMapToOtelAttributes(c.Labels) - registerTriggerFailureCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.registerTriggerFailureCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) incrementTriggerWorkflowStarterErrorCounter(ctx context.Context) { + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.triggerWorkflowStarterErrorCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) } func (c workflowsMetricLabeler) incrementCapabilityInvocationCounter(ctx context.Context) { - otelLabels := localMonitoring.KvMapToOtelAttributes(c.Labels) - capabilityInvocationCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.capabilityInvocationCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) } func (c workflowsMetricLabeler) updateWorkflowExecutionLatencyGauge(ctx context.Context, val int64) { - otelLabels := localMonitoring.KvMapToOtelAttributes(c.Labels) - workflowExecutionLatencyGauge.Record(ctx, val, metric.WithAttributes(otelLabels...)) + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.workflowExecutionLatencyGauge.Record(ctx, val, metric.WithAttributes(otelLabels...)) } func (c workflowsMetricLabeler) incrementTotalWorkflowStepErrorsCounter(ctx context.Context) { - otelLabels := localMonitoring.KvMapToOtelAttributes(c.Labels) - workflowStepErrorCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.workflowStepErrorCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) } func (c workflowsMetricLabeler) updateTotalWorkflowsGauge(ctx context.Context, val int64) { - otelLabels := localMonitoring.KvMapToOtelAttributes(c.Labels) - workflowsRunningGauge.Record(ctx, val, metric.WithAttributes(otelLabels...)) + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.workflowsRunningGauge.Record(ctx, val, metric.WithAttributes(otelLabels...)) } func (c workflowsMetricLabeler) incrementEngineHeartbeatCounter(ctx context.Context) { - otelLabels := localMonitoring.KvMapToOtelAttributes(c.Labels) - engineHeartbeatCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.engineHeartbeatCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) incrementCapabilityFailureCounter(ctx context.Context) { + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.capabilityFailureCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) incrementWorkflowRegisteredCounter(ctx context.Context) { + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.workflowRegisteredCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) incrementWorkflowUnregisteredCounter(ctx context.Context) { + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.workflowUnregisteredCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) incrementWorkflowInitializationCounter(ctx context.Context) { + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.workflowInitializationCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) updateWorkflowCompletedDurationHistogram(ctx context.Context, duration int64) { + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.workflowCompletedDurationSeconds.Record(ctx, duration, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) updateWorkflowEarlyExitDurationHistogram(ctx context.Context, duration int64) { + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.workflowEarlyExitDurationSeconds.Record(ctx, duration, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) updateWorkflowErrorDurationHistogram(ctx context.Context, duration int64) { + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.workflowErrorDurationSeconds.Record(ctx, duration, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) updateWorkflowTimeoutDurationHistogram(ctx context.Context, duration int64) { + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.workflowTimeoutDurationSeconds.Record(ctx, duration, metric.WithAttributes(otelLabels...)) +} + +func (c workflowsMetricLabeler) updateWorkflowStepDurationHistogram(ctx context.Context, duration int64) { + otelLabels := monutils.KvMapToOtelAttributes(c.Labels) + c.em.workflowStepDurationSeconds.Record(ctx, duration, metric.WithAttributes(otelLabels...)) } diff --git a/core/services/workflows/monitoring_test.go b/core/services/workflows/monitoring_test.go index 5910e583c95..5b7177e51dc 100644 --- a/core/services/workflows/monitoring_test.go +++ b/core/services/workflows/monitoring_test.go @@ -9,11 +9,12 @@ import ( ) func Test_InitMonitoringResources(t *testing.T) { - require.NoError(t, initMonitoringResources()) + _, err := initMonitoringResources() + require.NoError(t, err) } func Test_WorkflowMetricsLabeler(t *testing.T) { - testWorkflowsMetricLabeler := workflowsMetricLabeler{metrics.NewLabeler()} + testWorkflowsMetricLabeler := workflowsMetricLabeler{metrics.NewLabeler(), engineMetrics{}} testWorkflowsMetricLabeler2 := testWorkflowsMetricLabeler.with("foo", "baz") require.EqualValues(t, testWorkflowsMetricLabeler2.Labels["foo"], "baz") } diff --git a/core/services/workflows/syncer/contract_reader_mock.go b/core/services/workflows/syncer/contract_reader_mock.go index 61f59fa4e69..391ba5eacdb 100644 --- a/core/services/workflows/syncer/contract_reader_mock.go +++ b/core/services/workflows/syncer/contract_reader_mock.go @@ -6,6 +6,7 @@ import ( context "context" query "github.com/smartcontractkit/chainlink-common/pkg/types/query" + primitives "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" mock "github.com/stretchr/testify/mock" types "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -71,6 +72,68 @@ func (_c *MockContractReader_Bind_Call) RunAndReturn(run func(context.Context, [ return _c } +// GetLatestValueWithHeadData provides a mock function with given fields: ctx, readName, confidenceLevel, params, returnVal +func (_m *MockContractReader) GetLatestValueWithHeadData(ctx context.Context, readName string, confidenceLevel primitives.ConfidenceLevel, params any, returnVal any) (*types.Head, error) { + ret := _m.Called(ctx, readName, confidenceLevel, params, returnVal) + + if len(ret) == 0 { + panic("no return value specified for GetLatestValueWithHeadData") + } + + var r0 *types.Head + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, primitives.ConfidenceLevel, any, any) (*types.Head, error)); ok { + return rf(ctx, readName, confidenceLevel, params, returnVal) + } + if rf, ok := ret.Get(0).(func(context.Context, string, primitives.ConfidenceLevel, any, any) *types.Head); ok { + r0 = rf(ctx, readName, confidenceLevel, params, returnVal) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Head) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, primitives.ConfidenceLevel, any, any) error); ok { + r1 = rf(ctx, readName, confidenceLevel, params, returnVal) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockContractReader_GetLatestValueWithHeadData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLatestValueWithHeadData' +type MockContractReader_GetLatestValueWithHeadData_Call struct { + *mock.Call +} + +// GetLatestValueWithHeadData is a helper method to define mock.On call +// - ctx context.Context +// - readName string +// - confidenceLevel primitives.ConfidenceLevel +// - params any +// - returnVal any +func (_e *MockContractReader_Expecter) GetLatestValueWithHeadData(ctx interface{}, readName interface{}, confidenceLevel interface{}, params interface{}, returnVal interface{}) *MockContractReader_GetLatestValueWithHeadData_Call { + return &MockContractReader_GetLatestValueWithHeadData_Call{Call: _e.mock.On("GetLatestValueWithHeadData", ctx, readName, confidenceLevel, params, returnVal)} +} + +func (_c *MockContractReader_GetLatestValueWithHeadData_Call) Run(run func(ctx context.Context, readName string, confidenceLevel primitives.ConfidenceLevel, params any, returnVal any)) *MockContractReader_GetLatestValueWithHeadData_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(primitives.ConfidenceLevel), args[3].(any), args[4].(any)) + }) + return _c +} + +func (_c *MockContractReader_GetLatestValueWithHeadData_Call) Return(head *types.Head, err error) *MockContractReader_GetLatestValueWithHeadData_Call { + _c.Call.Return(head, err) + return _c +} + +func (_c *MockContractReader_GetLatestValueWithHeadData_Call) RunAndReturn(run func(context.Context, string, primitives.ConfidenceLevel, any, any) (*types.Head, error)) *MockContractReader_GetLatestValueWithHeadData_Call { + _c.Call.Return(run) + return _c +} + // QueryKey provides a mock function with given fields: _a0, _a1, _a2, _a3, _a4 func (_m *MockContractReader) QueryKey(_a0 context.Context, _a1 types.BoundContract, _a2 query.KeyFilter, _a3 query.LimitAndSort, _a4 any) ([]types.Sequence, error) { ret := _m.Called(_a0, _a1, _a2, _a3, _a4) diff --git a/core/services/workflows/syncer/fetcher.go b/core/services/workflows/syncer/fetcher.go index ed815a240ba..fdd0134909d 100644 --- a/core/services/workflows/syncer/fetcher.go +++ b/core/services/workflows/syncer/fetcher.go @@ -2,42 +2,113 @@ package syncer import ( "context" + "crypto/sha256" + "encoding/hex" "encoding/json" "fmt" "net/http" "strings" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" ) -func NewFetcherFunc( - ctx context.Context, - lggr logger.Logger, - och *webapi.OutgoingConnectorHandler) FetcherFunc { - return func(ctx context.Context, url string) ([]byte, error) { - payloadBytes, err := json.Marshal(ghcapabilities.Request{ - URL: url, - Method: http.MethodGet, - }) - if err != nil { - return nil, fmt.Errorf("failed to marshal fetch request: %w", err) - } +const ( + defaultFetchTimeoutMs = 20_000 +) - messageID := strings.Join([]string{ghcapabilities.MethodWorkflowSyncer, url}, "/") - resp, err := och.HandleSingleNodeRequest(ctx, messageID, payloadBytes) - if err != nil { - return nil, err +type FetcherService struct { + services.StateMachine + lggr logger.Logger + och *webapi.OutgoingConnectorHandler + wrapper gatewayConnector +} + +type gatewayConnector interface { + GetGatewayConnector() connector.GatewayConnector +} + +func NewFetcherService(lggr logger.Logger, wrapper gatewayConnector) *FetcherService { + return &FetcherService{ + lggr: lggr.Named("FetcherService"), + wrapper: wrapper, + } +} + +func (s *FetcherService) Start(ctx context.Context) error { + return s.StartOnce("FetcherService", func() error { + connector := s.wrapper.GetGatewayConnector() + + outgoingConnectorLggr := s.lggr.Named("OutgoingConnectorHandler") + + webAPIConfig := webapi.ServiceConfig{ + RateLimiter: common.RateLimiterConfig{ + GlobalRPS: 100.0, + GlobalBurst: 100, + PerSenderRPS: 100.0, + PerSenderBurst: 100, + }, } - lggr.Debugw("received gateway response", "resp", resp) - var payload ghcapabilities.Response - err = json.Unmarshal(resp.Body.Payload, &payload) + och, err := webapi.NewOutgoingConnectorHandler(connector, + webAPIConfig, + capabilities.MethodWorkflowSyncer, outgoingConnectorLggr) if err != nil { - return nil, err + return fmt.Errorf("could not create outgoing connector handler: %w", err) } - return payload.Body, nil + s.och = och + return och.Start(ctx) + }) +} + +func (s *FetcherService) Close() error { + return s.StopOnce("FetcherService", func() error { + return s.och.Close() + }) +} + +func (s *FetcherService) HealthReport() map[string]error { + return map[string]error{s.Name(): s.Healthy()} +} + +func (s *FetcherService) Name() string { + return s.lggr.Name() +} + +func hash(url string) string { + h := sha256.New() + h.Write([]byte(url)) + return hex.EncodeToString(h.Sum(nil)) +} + +func (s *FetcherService) Fetch(ctx context.Context, url string) ([]byte, error) { + payloadBytes, err := json.Marshal(ghcapabilities.Request{ + URL: url, + Method: http.MethodGet, + TimeoutMs: defaultFetchTimeoutMs, + }) + if err != nil { + return nil, fmt.Errorf("failed to marshal fetch request: %w", err) + } + + messageID := strings.Join([]string{ghcapabilities.MethodWorkflowSyncer, hash(url)}, "/") + resp, err := s.och.HandleSingleNodeRequest(ctx, messageID, payloadBytes) + if err != nil { + return nil, err } + + s.lggr.Debugw("received gateway response") + var payload ghcapabilities.Response + err = json.Unmarshal(resp.Body.Payload, &payload) + if err != nil { + return nil, err + } + + return payload.Body, nil } diff --git a/core/services/workflows/syncer/fetcher_test.go b/core/services/workflows/syncer/fetcher_test.go index 846a9186b5a..8e3e58fba0d 100644 --- a/core/services/workflows/syncer/fetcher_test.go +++ b/core/services/workflows/syncer/fetcher_test.go @@ -9,46 +9,48 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" gcmocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" - "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" ) -func TestNewFetcherFunc(t *testing.T) { +type wrapper struct { + c connector.GatewayConnector +} + +func (w *wrapper) GetGatewayConnector() connector.GatewayConnector { + return w.c +} + +func TestNewFetcherService(t *testing.T) { ctx := context.Background() lggr := logger.TestLogger(t) - config := webapi.ServiceConfig{ - RateLimiter: common.RateLimiterConfig{ - GlobalRPS: 100.0, - GlobalBurst: 100, - PerSenderRPS: 100.0, - PerSenderBurst: 100, - }, - } - connector := gcmocks.NewGatewayConnector(t) - och, err := webapi.NewOutgoingConnectorHandler(connector, config, ghcapabilities.MethodComputeAction, lggr) - require.NoError(t, err) + wrapper := &wrapper{c: connector} url := "http://example.com" - msgID := strings.Join([]string{ghcapabilities.MethodWorkflowSyncer, url}, "/") + msgID := strings.Join([]string{ghcapabilities.MethodWorkflowSyncer, hash(url)}, "/") t.Run("OK-valid_request", func(t *testing.T) { + connector.EXPECT().AddHandler([]string{capabilities.MethodWorkflowSyncer}, mock.Anything).Return(nil) + + fetcher := NewFetcherService(lggr, wrapper) + require.NoError(t, fetcher.Start(ctx)) + defer fetcher.Close() + gatewayResp := gatewayResponse(t, msgID) connector.EXPECT().SignAndSendToGateway(mock.Anything, "gateway1", mock.Anything).Run(func(ctx context.Context, gatewayID string, msg *api.MessageBody) { - och.HandleGatewayMessage(ctx, "gateway1", gatewayResp) + fetcher.och.HandleGatewayMessage(ctx, "gateway1", gatewayResp) }).Return(nil).Times(1) connector.EXPECT().DonID().Return("don-id") connector.EXPECT().GatewayIDs().Return([]string{"gateway1", "gateway2"}) - fetcher := NewFetcherFunc(ctx, lggr, och) - - payload, err := fetcher(ctx, url) + payload, err := fetcher.Fetch(ctx, url) require.NoError(t, err) expectedPayload := []byte("response body") diff --git a/core/services/workflows/syncer/handler.go b/core/services/workflows/syncer/handler.go index 7004c740c97..46dcd21ed90 100644 --- a/core/services/workflows/syncer/handler.go +++ b/core/services/workflows/syncer/handler.go @@ -1,18 +1,26 @@ package syncer import ( + "bytes" "context" - "crypto/sha256" "encoding/hex" + "encoding/json" "errors" "fmt" + "sync" + "time" + + "github.com/jonboulle/clockwork" "github.com/smartcontractkit/chainlink-common/pkg/custmsg" "github.com/smartcontractkit/chainlink-common/pkg/types/core" + pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/secrets" "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/platform" "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" "github.com/smartcontractkit/chainlink/v2/core/services/workflows" "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) @@ -51,14 +59,14 @@ type WorkflowRegistryForceUpdateSecretsRequestedV1 struct { } type WorkflowRegistryWorkflowRegisteredV1 struct { - WorkflowID [32]byte - WorkflowOwner []byte - DonID uint32 - Status uint8 - WorkflowName string - BinaryURL string - ConfigURL string - SecretsURL string + WorkflowID [32]byte + Owner []byte + DonID uint32 + Status uint8 + WorkflowName string + BinaryURL string + ConfigURL string + SecretsURL string } type WorkflowRegistryWorkflowUpdatedV1 struct { @@ -93,59 +101,157 @@ type WorkflowRegistryWorkflowDeletedV1 struct { WorkflowName string } -type secretsFetcher interface { - SecretsFor(ctx context.Context, workflowOwner, workflowName string) (map[string]string, error) +type lastFetchedAtMap struct { + m map[string]time.Time + sync.RWMutex } -// secretsFetcherFunc implements the secretsFetcher interface for a function. -type secretsFetcherFunc func(ctx context.Context, workflowOwner, workflowName string) (map[string]string, error) +func (l *lastFetchedAtMap) Set(url string, at time.Time) { + l.Lock() + defer l.Unlock() + l.m[url] = at +} -func (f secretsFetcherFunc) SecretsFor(ctx context.Context, workflowOwner, workflowName string) (map[string]string, error) { - return f(ctx, workflowOwner, workflowName) +func (l *lastFetchedAtMap) Get(url string) (time.Time, bool) { + l.RLock() + defer l.RUnlock() + got, ok := l.m[url] + return got, ok +} + +func newLastFetchedAtMap() *lastFetchedAtMap { + return &lastFetchedAtMap{ + m: map[string]time.Time{}, + } } // eventHandler is a handler for WorkflowRegistryEvent events. Each event type has a corresponding // method that handles the event. type eventHandler struct { - lggr logger.Logger - orm WorkflowRegistryDS - fetcher FetcherFunc - workflowStore store.Store - capRegistry core.CapabilitiesRegistry - engineRegistry *engineRegistry - emitter custmsg.MessageEmitter - secretsFetcher secretsFetcher + lggr logger.Logger + orm WorkflowRegistryDS + fetcher FetcherFunc + workflowStore store.Store + capRegistry core.CapabilitiesRegistry + engineRegistry *engineRegistry + emitter custmsg.MessageEmitter + lastFetchedAtMap *lastFetchedAtMap + clock clockwork.Clock + secretsFreshnessDuration time.Duration + encryptionKey workflowkey.Key +} + +type Event interface { + GetEventType() WorkflowRegistryEventType + GetData() any } -// newEventHandler returns a new eventHandler instance. -func newEventHandler( +var defaultSecretsFreshnessDuration = 24 * time.Hour + +// NewEventHandler returns a new eventHandler instance. +func NewEventHandler( lggr logger.Logger, orm ORM, gateway FetcherFunc, workflowStore store.Store, capRegistry core.CapabilitiesRegistry, - engineRegistry *engineRegistry, emitter custmsg.MessageEmitter, - secretsFetcher secretsFetcher, + clock clockwork.Clock, + encryptionKey workflowkey.Key, ) *eventHandler { return &eventHandler{ - lggr: lggr, - orm: orm, - fetcher: gateway, - workflowStore: workflowStore, - capRegistry: capRegistry, - engineRegistry: engineRegistry, - emitter: emitter, - secretsFetcher: secretsFetcher, + lggr: lggr, + orm: orm, + fetcher: gateway, + workflowStore: workflowStore, + capRegistry: capRegistry, + engineRegistry: newEngineRegistry(), + emitter: emitter, + lastFetchedAtMap: newLastFetchedAtMap(), + clock: clock, + secretsFreshnessDuration: defaultSecretsFreshnessDuration, + encryptionKey: encryptionKey, + } +} + +func (h *eventHandler) refreshSecrets(ctx context.Context, workflowOwner, workflowName, workflowID, secretsURLHash string) (string, error) { + owner, err := hex.DecodeString(workflowOwner) + if err != nil { + return "", err + } + + decodedHash, err := hex.DecodeString(secretsURLHash) + if err != nil { + return "", err + } + + updatedSecrets, err := h.forceUpdateSecretsEvent( + ctx, + WorkflowRegistryForceUpdateSecretsRequestedV1{ + SecretsURLHash: decodedHash, + Owner: owner, + WorkflowName: name, + }, + ) + if err != nil { + return "", err + } + + return updatedSecrets, nil +} + +func (h *eventHandler) SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) { + secretsURLHash, secretsPayload, err := h.orm.GetContentsByWorkflowID(ctx, workflowID) + if err != nil { + // The workflow record was found, but secrets_id was empty. + // Let's just stub out the response. + if errors.Is(err, ErrEmptySecrets) { + return map[string]string{}, nil + } + + return nil, fmt.Errorf("failed to fetch secrets by workflow ID: %w", err) + } + + lastFetchedAt, ok := h.lastFetchedAtMap.Get(secretsURLHash) + if !ok || h.clock.Now().Sub(lastFetchedAt) > h.secretsFreshnessDuration { + updatedSecrets, innerErr := h.refreshSecrets(ctx, workflowOwner, workflowName, workflowID, secretsURLHash) + if innerErr != nil { + msg := fmt.Sprintf("could not refresh secrets: proceeding with stale secrets for workflowID %s: %s", workflowID, innerErr) + h.lggr.Error(msg) + logCustMsg( + ctx, + h.emitter.With( + platform.KeyWorkflowID, workflowID, + platform.KeyWorkflowName, workflowName, + platform.KeyWorkflowOwner, workflowOwner, + ), + msg, + h.lggr, + ) + } else { + secretsPayload = updatedSecrets + } } + + res := secrets.EncryptedSecretsResult{} + err = json.Unmarshal([]byte(secretsPayload), &res) + if err != nil { + return nil, fmt.Errorf("could not unmarshal secrets: %w", err) + } + + return secrets.DecryptSecretsForNode( + res, + h.encryptionKey, + workflowOwner, + ) } -func (h *eventHandler) Handle(ctx context.Context, event WorkflowRegistryEvent) error { - switch event.EventType { +func (h *eventHandler) Handle(ctx context.Context, event Event) error { + switch event.GetEventType() { case ForceUpdateSecretsEvent: - payload, ok := event.Data.(WorkflowRegistryForceUpdateSecretsRequestedV1) + payload, ok := event.GetData().(WorkflowRegistryForceUpdateSecretsRequestedV1) if !ok { - return newHandlerTypeError(event.Data) + return newHandlerTypeError(event.GetData()) } cma := h.emitter.With( @@ -153,23 +259,24 @@ func (h *eventHandler) Handle(ctx context.Context, event WorkflowRegistryEvent) platform.KeyWorkflowOwner, hex.EncodeToString(payload.Owner), ) - if err := h.forceUpdateSecretsEvent(ctx, payload); err != nil { + if _, err := h.forceUpdateSecretsEvent(ctx, payload); err != nil { logCustMsg(ctx, cma, fmt.Sprintf("failed to handle force update secrets event: %v", err), h.lggr) return err } + h.lggr.Debugw("handled force update secrets events for URL hash", "urlHash", payload.SecretsURLHash) return nil case WorkflowRegisteredEvent: - payload, ok := event.Data.(WorkflowRegistryWorkflowRegisteredV1) + payload, ok := event.GetData().(WorkflowRegistryWorkflowRegisteredV1) if !ok { - return newHandlerTypeError(event.Data) + return newHandlerTypeError(event.GetData()) } wfID := hex.EncodeToString(payload.WorkflowID[:]) cma := h.emitter.With( platform.KeyWorkflowID, wfID, platform.KeyWorkflowName, payload.WorkflowName, - platform.KeyWorkflowOwner, hex.EncodeToString(payload.WorkflowOwner), + platform.KeyWorkflowOwner, hex.EncodeToString(payload.Owner), ) if err := h.workflowRegisteredEvent(ctx, payload); err != nil { @@ -177,12 +284,12 @@ func (h *eventHandler) Handle(ctx context.Context, event WorkflowRegistryEvent) return err } - h.lggr.Debugf("workflow 0x%x registered and started", wfID) + h.lggr.Debugw("handled workflow registration event", "workflowID", wfID) return nil case WorkflowUpdatedEvent: - payload, ok := event.Data.(WorkflowRegistryWorkflowUpdatedV1) + payload, ok := event.GetData().(WorkflowRegistryWorkflowUpdatedV1) if !ok { - return fmt.Errorf("invalid data type %T for event", event.Data) + return fmt.Errorf("invalid data type %T for event", event.GetData()) } newWorkflowID := hex.EncodeToString(payload.NewWorkflowID[:]) @@ -197,11 +304,12 @@ func (h *eventHandler) Handle(ctx context.Context, event WorkflowRegistryEvent) return err } + h.lggr.Debugw("handled workflow updated event", "workflowID", newWorkflowID) return nil case WorkflowPausedEvent: - payload, ok := event.Data.(WorkflowRegistryWorkflowPausedV1) + payload, ok := event.GetData().(WorkflowRegistryWorkflowPausedV1) if !ok { - return fmt.Errorf("invalid data type %T for event", event.Data) + return fmt.Errorf("invalid data type %T for event", event.GetData()) } wfID := hex.EncodeToString(payload.WorkflowID[:]) @@ -216,11 +324,12 @@ func (h *eventHandler) Handle(ctx context.Context, event WorkflowRegistryEvent) logCustMsg(ctx, cma, fmt.Sprintf("failed to handle workflow paused event: %v", err), h.lggr) return err } + h.lggr.Debugw("handled workflow paused event", "workflowID", wfID) return nil case WorkflowActivatedEvent: - payload, ok := event.Data.(WorkflowRegistryWorkflowActivatedV1) + payload, ok := event.GetData().(WorkflowRegistryWorkflowActivatedV1) if !ok { - return fmt.Errorf("invalid data type %T for event", event.Data) + return fmt.Errorf("invalid data type %T for event", event.GetData()) } wfID := hex.EncodeToString(payload.WorkflowID[:]) @@ -235,11 +344,12 @@ func (h *eventHandler) Handle(ctx context.Context, event WorkflowRegistryEvent) return err } + h.lggr.Debugw("handled workflow activated event", "workflowID", wfID) return nil case WorkflowDeletedEvent: - payload, ok := event.Data.(WorkflowRegistryWorkflowDeletedV1) + payload, ok := event.GetData().(WorkflowRegistryWorkflowDeletedV1) if !ok { - return fmt.Errorf("invalid data type %T for event", event.Data) + return fmt.Errorf("invalid data type %T for event", event.GetData()) } wfID := hex.EncodeToString(payload.WorkflowID[:]) @@ -255,9 +365,10 @@ func (h *eventHandler) Handle(ctx context.Context, event WorkflowRegistryEvent) return err } + h.lggr.Debugw("handled workflow deleted event", "workflowID", wfID) return nil default: - return fmt.Errorf("event type unsupported: %v", event.EventType) + return fmt.Errorf("event type unsupported: %v", event.GetEventType()) } } @@ -266,8 +377,6 @@ func (h *eventHandler) workflowRegisteredEvent( ctx context.Context, payload WorkflowRegistryWorkflowRegisteredV1, ) error { - wfID := hex.EncodeToString(payload.WorkflowID[:]) - // Download the contents of binaryURL, configURL and secretsURL and cache them locally. binary, err := h.fetcher(ctx, payload.BinaryURL) if err != nil { @@ -285,15 +394,18 @@ func (h *eventHandler) workflowRegisteredEvent( } // Calculate the hash of the binary and config files - hash := workflowID(binary, config, []byte(payload.SecretsURL)) + hash, err := pkgworkflows.GenerateWorkflowID(payload.Owner, binary, config, payload.SecretsURL) + if err != nil { + return fmt.Errorf("failed to generate workflow id: %w", err) + } // Pre-check: verify that the workflowID matches; if it doesn’t abort and log an error via Beholder. - if hash != wfID { - return fmt.Errorf("workflowID mismatch: %s != %s", hash, wfID) + if !bytes.Equal(hash[:], payload.WorkflowID[:]) { + return fmt.Errorf("workflowID mismatch: %x != %x", hash, payload.WorkflowID) } // Save the workflow secrets - urlHash, err := h.orm.GetSecretsURLHash(payload.WorkflowOwner, []byte(payload.SecretsURL)) + urlHash, err := h.orm.GetSecretsURLHash(payload.Owner, []byte(payload.SecretsURL)) if err != nil { return fmt.Errorf("failed to get secrets URL hash: %w", err) } @@ -304,12 +416,13 @@ func (h *eventHandler) workflowRegisteredEvent( status = job.WorkflowSpecStatusPaused } + wfID := hex.EncodeToString(payload.WorkflowID[:]) entry := &job.WorkflowSpec{ Workflow: hex.EncodeToString(binary), Config: string(config), WorkflowID: wfID, Status: status, - WorkflowOwner: hex.EncodeToString(payload.WorkflowOwner), + WorkflowOwner: hex.EncodeToString(payload.Owner), WorkflowName: payload.WorkflowName, SpecType: job.WASMFile, BinaryURL: payload.BinaryURL, @@ -320,6 +433,7 @@ func (h *eventHandler) workflowRegisteredEvent( } if status != job.WorkflowSpecStatusActive { + h.lggr.Debugw("workflow is marked as paused, so not starting it", "workflow", wfID) return nil } @@ -334,13 +448,13 @@ func (h *eventHandler) workflowRegisteredEvent( Lggr: h.lggr, Workflow: *sdkSpec, WorkflowID: wfID, - WorkflowOwner: hex.EncodeToString(payload.WorkflowOwner), + WorkflowOwner: string(payload.Owner), // this gets hex encoded in the engine. WorkflowName: payload.WorkflowName, Registry: h.capRegistry, Store: h.workflowStore, Config: config, Binary: binary, - SecretsFetcher: h.secretsFetcher, + SecretsFetcher: h, } e, err := workflows.NewEngine(ctx, cfg) if err != nil { @@ -352,6 +466,7 @@ func (h *eventHandler) workflowRegisteredEvent( } h.engineRegistry.Add(wfID, e) + return nil } @@ -368,14 +483,14 @@ func (h *eventHandler) workflowUpdatedEvent( } registeredEvent := WorkflowRegistryWorkflowRegisteredV1{ - WorkflowID: payload.NewWorkflowID, - WorkflowOwner: payload.WorkflowOwner, - DonID: payload.DonID, - Status: 0, - WorkflowName: payload.WorkflowName, - BinaryURL: payload.BinaryURL, - ConfigURL: payload.ConfigURL, - SecretsURL: payload.SecretsURL, + WorkflowID: payload.NewWorkflowID, + Owner: payload.WorkflowOwner, + DonID: payload.DonID, + Status: 0, + WorkflowName: payload.WorkflowName, + BinaryURL: payload.BinaryURL, + ConfigURL: payload.ConfigURL, + SecretsURL: payload.SecretsURL, } return h.workflowRegisteredEvent(ctx, registeredEvent) @@ -430,14 +545,14 @@ func (h *eventHandler) workflowActivatedEvent( // start a new workflow engine registeredEvent := WorkflowRegistryWorkflowRegisteredV1{ - WorkflowID: payload.WorkflowID, - WorkflowOwner: payload.WorkflowOwner, - DonID: payload.DonID, - Status: 0, - WorkflowName: payload.WorkflowName, - BinaryURL: spec.BinaryURL, - ConfigURL: spec.ConfigURL, - SecretsURL: secretsURL, + WorkflowID: payload.WorkflowID, + Owner: payload.WorkflowOwner, + DonID: payload.DonID, + Status: 0, + WorkflowName: payload.WorkflowName, + BinaryURL: spec.BinaryURL, + ConfigURL: spec.ConfigURL, + SecretsURL: secretsURL, } return h.workflowRegisteredEvent(ctx, registeredEvent) @@ -462,27 +577,29 @@ func (h *eventHandler) workflowDeletedEvent( func (h *eventHandler) forceUpdateSecretsEvent( ctx context.Context, payload WorkflowRegistryForceUpdateSecretsRequestedV1, -) error { +) (string, error) { // Get the URL of the secrets file from the event data hash := hex.EncodeToString(payload.SecretsURLHash) url, err := h.orm.GetSecretsURLByHash(ctx, hash) if err != nil { - return fmt.Errorf("failed to get URL by hash %s : %w", hash, err) + return "", fmt.Errorf("failed to get URL by hash %s : %w", hash, err) } // Fetch the contents of the secrets file from the url via the fetcher secrets, err := h.fetcher(ctx, url) if err != nil { - return fmt.Errorf("failed to fetch secrets from url %s : %w", url, err) + return "", err } + h.lastFetchedAtMap.Set(hash, h.clock.Now()) + // Update the secrets in the ORM if _, err := h.orm.Update(ctx, hash, string(secrets)); err != nil { - return fmt.Errorf("failed to update secrets: %w", err) + return "", fmt.Errorf("failed to update secrets: %w", err) } - return nil + return string(secrets), nil } // tryEngineCleanup attempts to stop the workflow engine for the given workflow ID. Does nothing if the @@ -503,15 +620,6 @@ func (h *eventHandler) tryEngineCleanup(wfID string) error { return nil } -// workflowID returns a hex encoded sha256 hash of the wasm, config and secretsURL. -func workflowID(wasm, config, secretsURL []byte) string { - sum := sha256.New() - sum.Write(wasm) - sum.Write(config) - sum.Write(secretsURL) - return hex.EncodeToString(sum.Sum(nil)) -} - // logCustMsg emits a custom message to the external sink and logs an error if that fails. func logCustMsg(ctx context.Context, cma custmsg.MessageEmitter, msg string, log logger.Logger) { err := cma.Emit(ctx, msg) diff --git a/core/services/workflows/syncer/handler_test.go b/core/services/workflows/syncer/handler_test.go index eb8b89ad7e1..bb0a61aea4d 100644 --- a/core/services/workflows/syncer/handler_test.go +++ b/core/services/workflows/syncer/handler_test.go @@ -2,16 +2,23 @@ package syncer import ( "context" + "database/sql" "encoding/hex" + "encoding/json" + "errors" "testing" + "time" "github.com/smartcontractkit/chainlink-common/pkg/custmsg" + pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/secrets" "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/wasmtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" wfstore "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" "github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer/mocks" "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" @@ -63,7 +70,7 @@ func Test_Handler(t *testing.T) { } mockORM.EXPECT().GetSecretsURLByHash(matches.AnyContext, giveHash).Return(giveURL, nil) mockORM.EXPECT().Update(matches.AnyContext, giveHash, "contents").Return(int64(1), nil) - h := newEventHandler(lggr, mockORM, fetcher, nil, nil, nil, emitter, nil) + h := NewEventHandler(lggr, mockORM, fetcher, nil, nil, emitter, clockwork.NewFakeClock(), workflowkey.Key{}) err = h.Handle(ctx, giveEvent) require.NoError(t, err) }) @@ -77,7 +84,7 @@ func Test_Handler(t *testing.T) { return []byte("contents"), nil } - h := newEventHandler(lggr, mockORM, fetcher, nil, nil, nil, emitter, nil) + h := NewEventHandler(lggr, mockORM, fetcher, nil, nil, emitter, clockwork.NewFakeClock(), workflowkey.Key{}) err := h.Handle(ctx, giveEvent) require.Error(t, err) require.Contains(t, err.Error(), "event type unsupported") @@ -86,7 +93,7 @@ func Test_Handler(t *testing.T) { t.Run("fails to get secrets url", func(t *testing.T) { mockORM := mocks.NewORM(t) ctx := testutils.Context(t) - h := newEventHandler(lggr, mockORM, nil, nil, nil, nil, emitter, nil) + h := NewEventHandler(lggr, mockORM, nil, nil, nil, emitter, clockwork.NewFakeClock(), workflowkey.Key{}) giveURL := "https://original-url.com" giveBytes, err := crypto.Keccak256([]byte(giveURL)) require.NoError(t, err) @@ -126,7 +133,7 @@ func Test_Handler(t *testing.T) { return nil, assert.AnError } mockORM.EXPECT().GetSecretsURLByHash(matches.AnyContext, giveHash).Return(giveURL, nil) - h := newEventHandler(lggr, mockORM, fetcher, nil, nil, nil, emitter, nil) + h := NewEventHandler(lggr, mockORM, fetcher, nil, nil, emitter, clockwork.NewFakeClock(), workflowkey.Key{}) err = h.Handle(ctx, giveEvent) require.Error(t, err) require.ErrorIs(t, err, assert.AnError) @@ -153,7 +160,7 @@ func Test_Handler(t *testing.T) { } mockORM.EXPECT().GetSecretsURLByHash(matches.AnyContext, giveHash).Return(giveURL, nil) mockORM.EXPECT().Update(matches.AnyContext, giveHash, "contents").Return(0, assert.AnError) - h := newEventHandler(lggr, mockORM, fetcher, nil, nil, nil, emitter, nil) + h := NewEventHandler(lggr, mockORM, fetcher, nil, nil, emitter, clockwork.NewFakeClock(), workflowkey.Key{}) err = h.Handle(ctx, giveEvent) require.Error(t, err) require.ErrorIs(t, err, assert.AnError) @@ -188,21 +195,17 @@ func Test_workflowRegisteredHandler(t *testing.T) { }) ) - giveWFID := workflowID(binary, config, []byte(secretsURL)) - - b, err := hex.DecodeString(giveWFID) + giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, binary, config, secretsURL) require.NoError(t, err) - wfID := make([]byte, 32) - copy(wfID, b) paused := WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(1), - WorkflowID: [32]byte(wfID), - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - SecretsURL: secretsURL, + Status: uint8(1), + WorkflowID: giveWFID, + Owner: wfOwner, + WorkflowName: "workflow-name", + BinaryURL: binaryURL, + ConfigURL: configURL, + SecretsURL: secretsURL, } h := &eventHandler{ @@ -244,21 +247,19 @@ func Test_workflowRegisteredHandler(t *testing.T) { }) ) - giveWFID := workflowID(binary, config, []byte(secretsURL)) + giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, binary, config, secretsURL) + require.NoError(t, err) - b, err := hex.DecodeString(giveWFID) require.NoError(t, err) - wfID := make([]byte, 32) - copy(wfID, b) active := WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(0), - WorkflowID: [32]byte(wfID), - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - SecretsURL: secretsURL, + Status: uint8(0), + WorkflowID: giveWFID, + Owner: wfOwner, + WorkflowName: "workflow-name", + BinaryURL: binaryURL, + ConfigURL: configURL, + SecretsURL: secretsURL, } er := newEngineRegistry() @@ -285,7 +286,7 @@ func Test_workflowRegisteredHandler(t *testing.T) { require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) // Verify the engine is started - engine, err := h.engineRegistry.Get(giveWFID) + engine, err := h.engineRegistry.Get(hex.EncodeToString(giveWFID[:])) require.NoError(t, err) err = engine.Ready() require.NoError(t, err) @@ -315,21 +316,19 @@ func Test_workflowDeletedHandler(t *testing.T) { }) ) - giveWFID := workflowID(binary, config, []byte(secretsURL)) + giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, binary, config, secretsURL) - b, err := hex.DecodeString(giveWFID) require.NoError(t, err) - wfID := make([]byte, 32) - copy(wfID, b) + wfIDs := hex.EncodeToString(giveWFID[:]) active := WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(0), - WorkflowID: [32]byte(wfID), - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - SecretsURL: secretsURL, + Status: uint8(0), + WorkflowID: giveWFID, + Owner: wfOwner, + WorkflowName: "workflow-name", + BinaryURL: binaryURL, + ConfigURL: configURL, + SecretsURL: secretsURL, } er := newEngineRegistry() @@ -356,13 +355,13 @@ func Test_workflowDeletedHandler(t *testing.T) { require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) // Verify the engine is started - engine, err := h.engineRegistry.Get(giveWFID) + engine, err := h.engineRegistry.Get(wfIDs) require.NoError(t, err) err = engine.Ready() require.NoError(t, err) deleteEvent := WorkflowRegistryWorkflowDeletedV1{ - WorkflowID: [32]byte(wfID), + WorkflowID: giveWFID, WorkflowOwner: wfOwner, WorkflowName: "workflow-name", DonID: 1, @@ -375,7 +374,7 @@ func Test_workflowDeletedHandler(t *testing.T) { require.Error(t, err) // Verify the engine is deleted - _, err = h.engineRegistry.Get(giveWFID) + _, err = h.engineRegistry.Get(wfIDs) require.Error(t, err) }) } @@ -406,27 +405,25 @@ func Test_workflowPausedActivatedUpdatedHandler(t *testing.T) { }) ) - giveWFID := workflowID(binary, config, []byte(secretsURL)) - updatedWFID := workflowID(binary, updateConfig, []byte(secretsURL)) + giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, binary, config, secretsURL) + require.NoError(t, err) + updatedWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, binary, updateConfig, secretsURL) + require.NoError(t, err) - b, err := hex.DecodeString(giveWFID) require.NoError(t, err) - wfID := make([]byte, 32) - copy(wfID, b) + wfIDs := hex.EncodeToString(giveWFID[:]) - b, err = hex.DecodeString(updatedWFID) require.NoError(t, err) - newWFID := make([]byte, 32) - copy(newWFID, b) + newWFIDs := hex.EncodeToString(updatedWFID[:]) active := WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(0), - WorkflowID: [32]byte(wfID), - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - SecretsURL: secretsURL, + Status: uint8(0), + WorkflowID: giveWFID, + Owner: wfOwner, + WorkflowName: "workflow-name", + BinaryURL: binaryURL, + ConfigURL: configURL, + SecretsURL: secretsURL, } er := newEngineRegistry() @@ -453,14 +450,14 @@ func Test_workflowPausedActivatedUpdatedHandler(t *testing.T) { require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) // Verify the engine is started - engine, err := h.engineRegistry.Get(giveWFID) + engine, err := h.engineRegistry.Get(wfIDs) require.NoError(t, err) err = engine.Ready() require.NoError(t, err) // create a paused event pauseEvent := WorkflowRegistryWorkflowPausedV1{ - WorkflowID: [32]byte(wfID), + WorkflowID: giveWFID, WorkflowOwner: wfOwner, WorkflowName: "workflow-name", DonID: 1, @@ -476,12 +473,12 @@ func Test_workflowPausedActivatedUpdatedHandler(t *testing.T) { require.Equal(t, job.WorkflowSpecStatusPaused, dbSpec.Status) // Verify the engine is removed - _, err = h.engineRegistry.Get(giveWFID) + _, err = h.engineRegistry.Get(wfIDs) require.Error(t, err) // create an activated workflow event activatedEvent := WorkflowRegistryWorkflowActivatedV1{ - WorkflowID: [32]byte(wfID), + WorkflowID: giveWFID, WorkflowOwner: wfOwner, WorkflowName: "workflow-name", DonID: 1, @@ -498,15 +495,15 @@ func Test_workflowPausedActivatedUpdatedHandler(t *testing.T) { require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) // Verify the engine is started - engine, err = h.engineRegistry.Get(giveWFID) + engine, err = h.engineRegistry.Get(wfIDs) require.NoError(t, err) err = engine.Ready() require.NoError(t, err) // create an updated event updatedEvent := WorkflowRegistryWorkflowUpdatedV1{ - OldWorkflowID: [32]byte(wfID), - NewWorkflowID: [32]byte(newWFID), + OldWorkflowID: giveWFID, + NewWorkflowID: updatedWFID, WorkflowOwner: wfOwner, WorkflowName: "workflow-name", BinaryURL: binaryURL, @@ -523,18 +520,237 @@ func Test_workflowPausedActivatedUpdatedHandler(t *testing.T) { require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) require.Equal(t, "workflow-name", dbSpec.WorkflowName) require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) - require.Equal(t, hex.EncodeToString(newWFID), dbSpec.WorkflowID) + require.Equal(t, newWFIDs, dbSpec.WorkflowID) require.Equal(t, newConfigURL, dbSpec.ConfigURL) require.Equal(t, string(updateConfig), dbSpec.Config) // old engine is no longer running - _, err = h.engineRegistry.Get(giveWFID) + _, err = h.engineRegistry.Get(wfIDs) require.Error(t, err) // new engine is started - engine, err = h.engineRegistry.Get(updatedWFID) + engine, err = h.engineRegistry.Get(newWFIDs) require.NoError(t, err) err = engine.Ready() require.NoError(t, err) }) } + +func Test_Handler_SecretsFor(t *testing.T) { + lggr := logger.TestLogger(t) + db := pgtest.NewSqlxDB(t) + orm := &orm{ds: db, lggr: lggr} + + workflowOwner := hex.EncodeToString([]byte("anOwner")) + workflowName := "aName" + workflowID := "anID" + encryptionKey, err := workflowkey.New() + require.NoError(t, err) + + url := "http://example.com" + hash := hex.EncodeToString([]byte(url)) + secretsPayload, err := generateSecrets(workflowOwner, map[string][]string{"Foo": []string{"Bar"}}, encryptionKey) + require.NoError(t, err) + secretsID, err := orm.Create(testutils.Context(t), url, hash, string(secretsPayload)) + require.NoError(t, err) + + _, err = orm.UpsertWorkflowSpec(testutils.Context(t), &job.WorkflowSpec{ + Workflow: "", + Config: "", + SecretsID: sql.NullInt64{Int64: secretsID, Valid: true}, + WorkflowID: workflowID, + WorkflowOwner: workflowOwner, + WorkflowName: workflowName, + BinaryURL: "", + ConfigURL: "", + CreatedAt: time.Now(), + SpecType: job.DefaultSpecType, + }) + require.NoError(t, err) + + fetcher := &mockFetcher{ + responseMap: map[string]mockFetchResp{ + url: mockFetchResp{Err: errors.New("could not fetch")}, + }, + } + h := NewEventHandler( + lggr, + orm, + fetcher.Fetch, + wfstore.NewDBStore(db, lggr, clockwork.NewFakeClock()), + capabilities.NewRegistry(lggr), + custmsg.NewLabeler(), + clockwork.NewFakeClock(), + encryptionKey, + ) + + gotSecrets, err := h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) + require.NoError(t, err) + + expectedSecrets := map[string]string{ + "Foo": "Bar", + } + assert.Equal(t, expectedSecrets, gotSecrets) +} + +func Test_Handler_SecretsFor_RefreshesSecrets(t *testing.T) { + lggr := logger.TestLogger(t) + db := pgtest.NewSqlxDB(t) + orm := &orm{ds: db, lggr: lggr} + + workflowOwner := hex.EncodeToString([]byte("anOwner")) + workflowName := "aName" + workflowID := "anID" + encryptionKey, err := workflowkey.New() + require.NoError(t, err) + + secretsPayload, err := generateSecrets(workflowOwner, map[string][]string{"Foo": []string{"Bar"}}, encryptionKey) + require.NoError(t, err) + + url := "http://example.com" + hash := hex.EncodeToString([]byte(url)) + + secretsID, err := orm.Create(testutils.Context(t), url, hash, string(secretsPayload)) + require.NoError(t, err) + + _, err = orm.UpsertWorkflowSpec(testutils.Context(t), &job.WorkflowSpec{ + Workflow: "", + Config: "", + SecretsID: sql.NullInt64{Int64: secretsID, Valid: true}, + WorkflowID: workflowID, + WorkflowOwner: workflowOwner, + WorkflowName: workflowName, + BinaryURL: "", + ConfigURL: "", + CreatedAt: time.Now(), + SpecType: job.DefaultSpecType, + }) + require.NoError(t, err) + + secretsPayload, err = generateSecrets(workflowOwner, map[string][]string{"Baz": []string{"Bar"}}, encryptionKey) + require.NoError(t, err) + fetcher := &mockFetcher{ + responseMap: map[string]mockFetchResp{ + url: mockFetchResp{Body: secretsPayload}, + }, + } + h := NewEventHandler( + lggr, + orm, + fetcher.Fetch, + wfstore.NewDBStore(db, lggr, clockwork.NewFakeClock()), + capabilities.NewRegistry(lggr), + custmsg.NewLabeler(), + clockwork.NewFakeClock(), + encryptionKey, + ) + + gotSecrets, err := h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) + require.NoError(t, err) + + expectedSecrets := map[string]string{ + "Baz": "Bar", + } + assert.Equal(t, expectedSecrets, gotSecrets) +} + +func Test_Handler_SecretsFor_RefreshLogic(t *testing.T) { + lggr := logger.TestLogger(t) + db := pgtest.NewSqlxDB(t) + orm := &orm{ds: db, lggr: lggr} + + workflowOwner := hex.EncodeToString([]byte("anOwner")) + workflowName := "aName" + workflowID := "anID" + encryptionKey, err := workflowkey.New() + require.NoError(t, err) + + secretsPayload, err := generateSecrets(workflowOwner, map[string][]string{"Foo": []string{"Bar"}}, encryptionKey) + require.NoError(t, err) + + url := "http://example.com" + hash := hex.EncodeToString([]byte(url)) + + secretsID, err := orm.Create(testutils.Context(t), url, hash, string(secretsPayload)) + require.NoError(t, err) + + _, err = orm.UpsertWorkflowSpec(testutils.Context(t), &job.WorkflowSpec{ + Workflow: "", + Config: "", + SecretsID: sql.NullInt64{Int64: secretsID, Valid: true}, + WorkflowID: workflowID, + WorkflowOwner: workflowOwner, + WorkflowName: workflowName, + BinaryURL: "", + ConfigURL: "", + CreatedAt: time.Now(), + SpecType: job.DefaultSpecType, + }) + require.NoError(t, err) + + fetcher := &mockFetcher{ + responseMap: map[string]mockFetchResp{ + url: mockFetchResp{ + Body: secretsPayload, + }, + }, + } + clock := clockwork.NewFakeClock() + h := NewEventHandler( + lggr, + orm, + fetcher.Fetch, + wfstore.NewDBStore(db, lggr, clockwork.NewFakeClock()), + capabilities.NewRegistry(lggr), + custmsg.NewLabeler(), + clock, + encryptionKey, + ) + + gotSecrets, err := h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) + require.NoError(t, err) + + expectedSecrets := map[string]string{ + "Foo": "Bar", + } + assert.Equal(t, expectedSecrets, gotSecrets) + + // Now stub out an unparseable response, since we already fetched it recently above, we shouldn't need to refetch + // SecretsFor should still succeed. + fetcher.responseMap[url] = mockFetchResp{} + + gotSecrets, err = h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) + require.NoError(t, err) + + assert.Equal(t, expectedSecrets, gotSecrets) + + // Now advance so that we hit the freshness limit + clock.Advance(48 * time.Hour) + + _, err = h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) + assert.ErrorContains(t, err, "unexpected end of JSON input") +} + +func generateSecrets(workflowOwner string, secretsMap map[string][]string, encryptionKey workflowkey.Key) ([]byte, error) { + sm, secretsEnvVars, err := secrets.EncryptSecretsForNodes( + workflowOwner, + secretsMap, + map[string][32]byte{ + "p2pId": encryptionKey.PublicKey(), + }, + secrets.SecretsConfig{}, + ) + if err != nil { + return nil, err + } + return json.Marshal(secrets.EncryptedSecretsResult{ + EncryptedSecrets: sm, + Metadata: secrets.Metadata{ + WorkflowOwner: workflowOwner, + EnvVarsAssignedToNodes: secretsEnvVars, + NodePublicEncryptionKeys: map[string]string{ + "p2pId": encryptionKey.PublicKeyString(), + }, + }, + }) +} diff --git a/core/services/workflows/syncer/mocks/orm.go b/core/services/workflows/syncer/mocks/orm.go index 128100ea907..da96f422361 100644 --- a/core/services/workflows/syncer/mocks/orm.go +++ b/core/services/workflows/syncer/mocks/orm.go @@ -243,6 +243,70 @@ func (_c *ORM_GetContentsByHash_Call) RunAndReturn(run func(context.Context, str return _c } +// GetContentsByWorkflowID provides a mock function with given fields: ctx, workflowID +func (_m *ORM) GetContentsByWorkflowID(ctx context.Context, workflowID string) (string, string, error) { + ret := _m.Called(ctx, workflowID) + + if len(ret) == 0 { + panic("no return value specified for GetContentsByWorkflowID") + } + + var r0 string + var r1 string + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, string) (string, string, error)); ok { + return rf(ctx, workflowID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) string); ok { + r0 = rf(ctx, workflowID) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) string); ok { + r1 = rf(ctx, workflowID) + } else { + r1 = ret.Get(1).(string) + } + + if rf, ok := ret.Get(2).(func(context.Context, string) error); ok { + r2 = rf(ctx, workflowID) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// ORM_GetContentsByWorkflowID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetContentsByWorkflowID' +type ORM_GetContentsByWorkflowID_Call struct { + *mock.Call +} + +// GetContentsByWorkflowID is a helper method to define mock.On call +// - ctx context.Context +// - workflowID string +func (_e *ORM_Expecter) GetContentsByWorkflowID(ctx interface{}, workflowID interface{}) *ORM_GetContentsByWorkflowID_Call { + return &ORM_GetContentsByWorkflowID_Call{Call: _e.mock.On("GetContentsByWorkflowID", ctx, workflowID)} +} + +func (_c *ORM_GetContentsByWorkflowID_Call) Run(run func(ctx context.Context, workflowID string)) *ORM_GetContentsByWorkflowID_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *ORM_GetContentsByWorkflowID_Call) Return(_a0 string, _a1 string, _a2 error) *ORM_GetContentsByWorkflowID_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *ORM_GetContentsByWorkflowID_Call) RunAndReturn(run func(context.Context, string) (string, string, error)) *ORM_GetContentsByWorkflowID_Call { + _c.Call.Return(run) + return _c +} + // GetSecretsURLByHash provides a mock function with given fields: ctx, hash func (_m *ORM) GetSecretsURLByHash(ctx context.Context, hash string) (string, error) { ret := _m.Called(ctx, hash) diff --git a/core/services/workflows/syncer/orm.go b/core/services/workflows/syncer/orm.go index d1f2d55a3a1..97f2c834f36 100644 --- a/core/services/workflows/syncer/orm.go +++ b/core/services/workflows/syncer/orm.go @@ -3,6 +3,7 @@ package syncer import ( "context" "database/sql" + "errors" "fmt" "time" @@ -25,6 +26,9 @@ type WorkflowSecretsDS interface { // GetContentsByHash returns the contents of the secret at the given hashed URL. GetContentsByHash(ctx context.Context, hash string) (string, error) + // GetContentsByWorkflowID returns the contents and secrets_url of the secret for the given workflow. + GetContentsByWorkflowID(ctx context.Context, workflowID string) (string, string, error) + // GetSecretsURLHash returns the keccak256 hash of the owner and secrets URL. GetSecretsURLHash(owner, secretsURL []byte) ([]byte, error) @@ -123,6 +127,43 @@ func (orm *orm) GetContents(ctx context.Context, url string) (string, error) { return contents, nil // Return the populated Artifact struct } +type Int struct { + sql.NullInt64 +} + +type joinRecord struct { + SecretsID sql.NullString `db:"wspec_secrets_id"` + SecretsURLHash sql.NullString `db:"wsec_secrets_url_hash"` + Contents sql.NullString `db:"wsec_contents"` +} + +var ErrEmptySecrets = errors.New("secrets field is empty") + +// GetContentsByWorkflowID joins the workflow_secrets on the workflow_specs table and gets +// the associated secrets contents. +func (orm *orm) GetContentsByWorkflowID(ctx context.Context, workflowID string) (string, string, error) { + var jr joinRecord + err := orm.ds.GetContext( + ctx, + &jr, + `SELECT wsec.secrets_url_hash AS wsec_secrets_url_hash, wsec.contents AS wsec_contents, wspec.secrets_id AS wspec_secrets_id + FROM workflow_specs AS wspec + LEFT JOIN + workflow_secrets AS wsec ON wspec.secrets_id = wsec.id + WHERE wspec.workflow_id = $1`, + workflowID, + ) + if err != nil { + return "", "", err + } + + if !jr.SecretsID.Valid { + return "", "", ErrEmptySecrets + } + + return jr.SecretsURLHash.String, jr.Contents.String, nil +} + // Update updates the secrets content at the given hash or inserts a new record if not found. func (orm *orm) Update(ctx context.Context, hash, contents string) (int64, error) { var id int64 diff --git a/core/services/workflows/syncer/orm_test.go b/core/services/workflows/syncer/orm_test.go index 1be4e54f472..08c60447498 100644 --- a/core/services/workflows/syncer/orm_test.go +++ b/core/services/workflows/syncer/orm_test.go @@ -196,3 +196,63 @@ func Test_GetWorkflowSpec(t *testing.T) { require.Nil(t, dbSpec) }) } + +func Test_GetContentsByWorkflowID(t *testing.T) { + db := pgtest.NewSqlxDB(t) + ctx := testutils.Context(t) + lggr := logger.TestLogger(t) + orm := &orm{ds: db, lggr: lggr} + + // workflow_id is missing + _, _, err := orm.GetContentsByWorkflowID(ctx, "doesnt-exist") + require.ErrorContains(t, err, "no rows in result set") + + // secrets_id is nil; should return EmptySecrets + workflowID := "aWorkflowID" + _, err = orm.UpsertWorkflowSpec(ctx, &job.WorkflowSpec{ + Workflow: "", + Config: "", + WorkflowID: workflowID, + WorkflowOwner: "aWorkflowOwner", + WorkflowName: "aWorkflowName", + BinaryURL: "", + ConfigURL: "", + CreatedAt: time.Now(), + SpecType: job.DefaultSpecType, + }) + require.NoError(t, err) + + _, _, err = orm.GetContentsByWorkflowID(ctx, workflowID) + require.ErrorIs(t, err, ErrEmptySecrets) + + // retrieves the artifact if provided + giveURL := "https://example.com" + giveBytes, err := crypto.Keccak256([]byte(giveURL)) + require.NoError(t, err) + giveHash := hex.EncodeToString(giveBytes) + giveContent := "some contents" + + secretsID, err := orm.Create(ctx, giveURL, giveHash, giveContent) + require.NoError(t, err) + + _, err = orm.UpsertWorkflowSpec(ctx, &job.WorkflowSpec{ + Workflow: "", + Config: "", + SecretsID: sql.NullInt64{Int64: secretsID, Valid: true}, + WorkflowID: workflowID, + WorkflowOwner: "aWorkflowOwner", + WorkflowName: "aWorkflowName", + BinaryURL: "", + ConfigURL: "", + CreatedAt: time.Now(), + SpecType: job.DefaultSpecType, + }) + require.NoError(t, err) + _, err = orm.GetWorkflowSpec(ctx, "aWorkflowOwner", "aWorkflowName") + require.NoError(t, err) + + gotHash, gotContent, err := orm.GetContentsByWorkflowID(ctx, workflowID) + require.NoError(t, err) + assert.Equal(t, giveHash, gotHash) + assert.Equal(t, giveContent, gotContent) +} diff --git a/core/services/workflows/syncer/workflow_registry.go b/core/services/workflows/syncer/workflow_registry.go index cdd0c71acc0..024975539af 100644 --- a/core/services/workflows/syncer/workflow_registry.go +++ b/core/services/workflows/syncer/workflow_registry.go @@ -4,30 +4,27 @@ import ( "context" "encoding/hex" "encoding/json" - "errors" "fmt" - "strconv" "sync" "time" - "github.com/smartcontractkit/chainlink-common/pkg/custmsg" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/services" types "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/types/core" query "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" "github.com/smartcontractkit/chainlink/v2/core/logger" evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) const name = "WorkflowRegistrySyncer" var ( - defaultTickInterval = 12 * time.Second - ContractName = "WorkflowRegistry" + defaultTickInterval = 12 * time.Second + WorkflowRegistryContractName = "WorkflowRegistry" + GetWorkflowMetadataListByDONMethodName = "getWorkflowMetadataListByDON" ) type Head struct { @@ -36,6 +33,16 @@ type Head struct { Timestamp uint64 } +type GetWorkflowMetadataListByDONParams struct { + DonID uint32 + Start uint64 + Limit uint64 +} + +type GetWorkflowMetadataListByDONReturnVal struct { + WorkflowMetadataList []WorkflowRegistryWorkflowRegisteredV1 +} + // WorkflowRegistryEvent is an event emitted by the WorkflowRegistry. Each event is typed // so that the consumer can determine how to handle the event. type WorkflowRegistryEvent struct { @@ -45,21 +52,28 @@ type WorkflowRegistryEvent struct { Head Head } +func (we WorkflowRegistryEvent) GetEventType() WorkflowRegistryEventType { + return we.EventType +} + +func (we WorkflowRegistryEvent) GetData() any { + return we.Data +} + // WorkflowRegistryEventResponse is a response to either parsing a queried event or handling the event. type WorkflowRegistryEventResponse struct { Err error Event *WorkflowRegistryEvent } -// ContractEventPollerConfig is the configuration needed to poll for events on a contract. Currently +// WorkflowEventPollerConfig is the configuration needed to poll for events on a contract. Currently // requires the ContractEventName. -// -// TODO(mstreet3): Use LookbackBlocks instead of StartBlockNum -type ContractEventPollerConfig struct { - ContractName string - ContractAddress string - StartBlockNum uint64 - QueryCount uint64 +type WorkflowEventPollerConfig struct { + QueryCount uint64 +} + +type WorkflowLoadConfig struct { + FetchBatchSize int } // FetcherFunc is an abstraction for fetching the contents stored at a URL. @@ -73,6 +87,7 @@ type ContractReaderFactory interface { type ContractReader interface { Bind(context.Context, []types.BoundContract) error QueryKey(context.Context, types.BoundContract, query.KeyFilter, query.LimitAndSort, any) ([]types.Sequence, error) + GetLatestValueWithHeadData(ctx context.Context, readName string, confidenceLevel primitives.ConfidenceLevel, params any, returnVal any) (head *types.Head, err error) } // WorkflowRegistrySyncer is the public interface of the package. @@ -95,23 +110,18 @@ type workflowRegistry struct { // ticker is the interval at which the workflowRegistry will poll the contract for events. ticker <-chan time.Time - lggr logger.Logger - emitter custmsg.Labeler - orm WorkflowRegistryDS - reader ContractReader - gateway FetcherFunc + lggr logger.Logger + workflowRegistryAddress string - // initReader allows the workflowRegistry to initialize a contract reader if one is not provided - // and separates the contract reader initialization from the workflowRegistry start up. - initReader func(context.Context, logger.Logger, ContractReaderFactory, types.BoundContract) (types.ContractReader, error) - relayer ContractReaderFactory + newContractReaderFn newContractReaderFn - cfg ContractEventPollerConfig - eventTypes []WorkflowRegistryEventType + eventPollerCfg WorkflowEventPollerConfig + eventTypes []WorkflowRegistryEventType // eventsCh is read by the handler and each event is handled once received. - eventsCh chan WorkflowRegistryEventResponse - handler *eventHandler + eventsCh chan WorkflowRegistryEventResponse + handler evtHandler + initialWorkflowsStateLoader initialWorkflowsStateLoader // batchCh is a channel that receives batches of events from the contract query goroutines. batchCh chan []WorkflowRegistryEventResponse @@ -120,9 +130,9 @@ type workflowRegistry struct { // default min heap is sorted by block height. heap Heap - workflowStore store.Store - capRegistry core.CapabilitiesRegistry - engineRegistry *engineRegistry + workflowDonNotifier donNotifier + + reader ContractReader } // WithTicker allows external callers to provide a ticker to the workflowRegistry. This is useful @@ -133,51 +143,50 @@ func WithTicker(ticker <-chan time.Time) func(*workflowRegistry) { } } -func WithReader(reader types.ContractReader) func(*workflowRegistry) { - return func(wr *workflowRegistry) { - wr.reader = reader - } +type evtHandler interface { + Handle(ctx context.Context, event Event) error +} + +type initialWorkflowsStateLoader interface { + // LoadWorkflows loads all the workflows for the given donID from the contract. Returns the head of the chain as of the + // point in time at which the load occurred. + LoadWorkflows(ctx context.Context, don capabilities.DON) (*types.Head, error) } +type donNotifier interface { + WaitForDon(ctx context.Context) (capabilities.DON, error) +} + +type newContractReaderFn func(context.Context, []byte) (ContractReader, error) + // NewWorkflowRegistry returns a new workflowRegistry. // Only queries for WorkflowRegistryForceUpdateSecretsRequestedV1 events. -func NewWorkflowRegistry[T ContractReader]( +func NewWorkflowRegistry( lggr logger.Logger, - orm WorkflowRegistryDS, - reader T, - gateway FetcherFunc, + newContractReaderFn newContractReaderFn, addr string, - workflowStore store.Store, - capRegistry core.CapabilitiesRegistry, - emitter custmsg.Labeler, + eventPollerConfig WorkflowEventPollerConfig, + handler evtHandler, + initialWorkflowsStateLoader initialWorkflowsStateLoader, + workflowDonNotifier donNotifier, opts ...func(*workflowRegistry), ) *workflowRegistry { ets := []WorkflowRegistryEventType{ForceUpdateSecretsEvent} wr := &workflowRegistry{ - lggr: lggr.Named(name), - emitter: emitter, - orm: orm, - reader: reader, - gateway: gateway, - workflowStore: workflowStore, - capRegistry: capRegistry, - engineRegistry: newEngineRegistry(), - cfg: ContractEventPollerConfig{ - ContractName: ContractName, - ContractAddress: addr, - QueryCount: 20, - StartBlockNum: 0, - }, - initReader: newReader, - heap: newBlockHeightHeap(), - stopCh: make(services.StopChan), - eventTypes: ets, - eventsCh: make(chan WorkflowRegistryEventResponse), - batchCh: make(chan []WorkflowRegistryEventResponse, len(ets)), + lggr: lggr, + newContractReaderFn: newContractReaderFn, + workflowRegistryAddress: addr, + eventPollerCfg: eventPollerConfig, + heap: newBlockHeightHeap(), + stopCh: make(services.StopChan), + eventTypes: ets, + eventsCh: make(chan WorkflowRegistryEventResponse), + batchCh: make(chan []WorkflowRegistryEventResponse, len(ets)), + handler: handler, + initialWorkflowsStateLoader: initialWorkflowsStateLoader, + workflowDonNotifier: workflowDonNotifier, } - wr.handler = newEventHandler(wr.lggr, wr.orm, wr.gateway, wr.workflowStore, wr.capRegistry, - wr.engineRegistry, wr.emitter, secretsFetcherFunc(wr.SecretsFor), - ) + for _, opt := range opts { opt(wr) } @@ -195,7 +204,21 @@ func (w *workflowRegistry) Start(_ context.Context) error { defer w.wg.Done() defer cancel() - w.syncEventsLoop(ctx) + w.lggr.Debugw("Waiting for DON...") + don, err := w.workflowDonNotifier.WaitForDon(ctx) + if err != nil { + w.lggr.Errorf("failed to wait for don: %v", err) + return + } + + w.lggr.Debugw("Loading initial workflows for DON", "DON", don.ID) + loadWorkflowsHead, err := w.initialWorkflowsStateLoader.LoadWorkflows(ctx, don) + if err != nil { + w.lggr.Errorf("failed to load workflows: %v", err) + return + } + + w.syncEventsLoop(ctx, loadWorkflowsHead.Height) }() w.wg.Add(1) @@ -230,10 +253,6 @@ func (w *workflowRegistry) Name() string { return name } -func (w *workflowRegistry) SecretsFor(ctx context.Context, workflowOwner, workflowName string) (map[string]string, error) { - return nil, errors.New("not implemented") -} - // handlerLoop handles the events that are emitted by the contract. func (w *workflowRegistry) handlerLoop(ctx context.Context) { for { @@ -261,7 +280,7 @@ func (w *workflowRegistry) handlerLoop(ctx context.Context) { } // syncEventsLoop polls the contract for events and passes them to a channel for handling. -func (w *workflowRegistry) syncEventsLoop(ctx context.Context) { +func (w *workflowRegistry) syncEventsLoop(ctx context.Context, lastReadBlockNumber string) { var ( // sendLog is a helper that sends a WorkflowRegistryEventResponse to the eventsCh in a // blocking way that will send the response or be canceled. @@ -298,7 +317,12 @@ func (w *workflowRegistry) syncEventsLoop(ctx context.Context) { signal, w.lggr, reader, - w.cfg, + lastReadBlockNumber, + queryEventConfig{ + ContractName: WorkflowRegistryContractName, + ContractAddress: w.workflowRegistryAddress, + WorkflowEventPollerConfig: w.eventPollerCfg, + }, w.eventTypes[i], w.batchCh, ) @@ -311,6 +335,7 @@ func (w *workflowRegistry) syncEventsLoop(ctx context.Context) { case <-ctx.Done(): return case <-ticker: + w.lggr.Debugw("Syncing with WorkflowRegistry") // for each event type, send a signal for it to execute a query and produce a new // batch of event logs for i := 0; i < len(w.eventTypes); i++ { @@ -376,12 +401,12 @@ func (w *workflowRegistry) getTicker() <-chan time.Time { // reader. func (w *workflowRegistry) getContractReader(ctx context.Context) (ContractReader, error) { c := types.BoundContract{ - Name: w.cfg.ContractName, - Address: w.cfg.ContractAddress, + Name: WorkflowRegistryContractName, + Address: w.workflowRegistryAddress, } if w.reader == nil { - reader, err := w.initReader(ctx, w.lggr, w.relayer, c) + reader, err := getWorkflowRegistryEventReader(ctx, w.newContractReaderFn, c) if err != nil { return nil, err } @@ -392,6 +417,12 @@ func (w *workflowRegistry) getContractReader(ctx context.Context) (ContractReade return w.reader, nil } +type queryEventConfig struct { + ContractName string + ContractAddress string + WorkflowEventPollerConfig +} + // queryEvent queries the contract for events of the given type on each tick from the ticker. // Sends a batch of event logs to the batch channel. The batch represents all the // event logs read since the last query. Loops until the context is canceled. @@ -400,7 +431,8 @@ func queryEvent( ticker <-chan struct{}, lggr logger.Logger, reader ContractReader, - cfg ContractEventPollerConfig, + lastReadBlockNumber string, + cfg queryEventConfig, et WorkflowRegistryEventType, batchCh chan<- []WorkflowRegistryEventResponse, ) { @@ -436,7 +468,7 @@ func queryEvent( Key: string(et), Expressions: []query.Expression{ query.Confidence(primitives.Finalized), - query.Block(strconv.FormatUint(cfg.StartBlockNum, 10), primitives.Gte), + query.Block(lastReadBlockNumber, primitives.Gt), }, }, limitAndSort, @@ -470,15 +502,14 @@ func queryEvent( } } -func newReader( +func getWorkflowRegistryEventReader( ctx context.Context, - lggr logger.Logger, - factory ContractReaderFactory, + newReaderFn newContractReaderFn, bc types.BoundContract, -) (types.ContractReader, error) { +) (ContractReader, error) { contractReaderCfg := evmtypes.ChainReaderConfig{ Contracts: map[string]evmtypes.ChainContractReader{ - ContractName: { + WorkflowRegistryContractName: { ContractPollingFilter: evmtypes.ContractPollingFilter{ GenericEventNames: []string{string(ForceUpdateSecretsEvent)}, }, @@ -498,7 +529,7 @@ func newReader( return nil, err } - reader, err := factory.NewContractReader(ctx, marshalledCfg) + reader, err := newReaderFn(ctx, marshalledCfg) if err != nil { return nil, err } @@ -511,6 +542,111 @@ func newReader( return reader, nil } +type workflowAsEvent struct { + Data WorkflowRegistryWorkflowRegisteredV1 + EventType WorkflowRegistryEventType +} + +func (r workflowAsEvent) GetEventType() WorkflowRegistryEventType { + return r.EventType +} + +func (r workflowAsEvent) GetData() any { + return r.Data +} + +type workflowRegistryContractLoader struct { + lggr logger.Logger + workflowRegistryAddress string + newContractReaderFn newContractReaderFn + handler evtHandler +} + +func NewWorkflowRegistryContractLoader( + lggr logger.Logger, + workflowRegistryAddress string, + newContractReaderFn newContractReaderFn, + handler evtHandler, +) *workflowRegistryContractLoader { + return &workflowRegistryContractLoader{ + lggr: lggr.Named("WorkflowRegistryContractLoader"), + workflowRegistryAddress: workflowRegistryAddress, + newContractReaderFn: newContractReaderFn, + handler: handler, + } +} + +func (l *workflowRegistryContractLoader) LoadWorkflows(ctx context.Context, don capabilities.DON) (*types.Head, error) { + // Build the ContractReader config + contractReaderCfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + WorkflowRegistryContractName: { + ContractABI: workflow_registry_wrapper.WorkflowRegistryABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + GetWorkflowMetadataListByDONMethodName: { + ChainSpecificName: GetWorkflowMetadataListByDONMethodName, + }, + }, + }, + }, + } + + contractReaderCfgBytes, err := json.Marshal(contractReaderCfg) + if err != nil { + return nil, fmt.Errorf("failed to marshal contract reader config: %w", err) + } + + contractReader, err := l.newContractReaderFn(ctx, contractReaderCfgBytes) + if err != nil { + return nil, fmt.Errorf("failed to create contract reader: %w", err) + } + + err = contractReader.Bind(ctx, []types.BoundContract{{Name: WorkflowRegistryContractName, Address: l.workflowRegistryAddress}}) + if err != nil { + return nil, fmt.Errorf("failed to bind contract reader: %w", err) + } + + contractBinding := types.BoundContract{ + Address: l.workflowRegistryAddress, + Name: WorkflowRegistryContractName, + } + + readIdentifier := contractBinding.ReadIdentifier(GetWorkflowMetadataListByDONMethodName) + params := GetWorkflowMetadataListByDONParams{ + DonID: don.ID, + Start: 0, + Limit: 0, // 0 tells the contract to return max pagination limit workflows on each call + } + + var headAtLastRead *types.Head + for { + var err error + var workflows GetWorkflowMetadataListByDONReturnVal + headAtLastRead, err = contractReader.GetLatestValueWithHeadData(ctx, readIdentifier, primitives.Finalized, params, &workflows) + if err != nil { + return nil, fmt.Errorf("failed to get workflow metadata for don %w", err) + } + + l.lggr.Debugw("Rehydrating existing workflows", "len", len(workflows.WorkflowMetadataList)) + for _, workflow := range workflows.WorkflowMetadataList { + if err = l.handler.Handle(ctx, workflowAsEvent{ + Data: workflow, + EventType: WorkflowRegisteredEvent, + }); err != nil { + l.lggr.Errorf("failed to handle workflow registration: %s", err) + } + } + + if len(workflows.WorkflowMetadataList) == 0 { + break + } + + params.Start += uint64(len(workflows.WorkflowMetadataList)) + } + + return headAtLastRead, nil +} + // toWorkflowRegistryEventResponse converts a types.Sequence to a WorkflowRegistryEventResponse. func toWorkflowRegistryEventResponse( log types.Sequence, @@ -554,38 +690,3 @@ func toWorkflowRegistryEventResponse( return resp } - -type nullWorkflowRegistrySyncer struct { - services.Service -} - -func NewNullWorkflowRegistrySyncer() *nullWorkflowRegistrySyncer { - return &nullWorkflowRegistrySyncer{} -} - -// Start -func (u *nullWorkflowRegistrySyncer) Start(context.Context) error { - return nil -} - -// Close -func (u *nullWorkflowRegistrySyncer) Close() error { - return nil -} - -// SecretsFor -func (u *nullWorkflowRegistrySyncer) SecretsFor(context.Context, string, string) (map[string]string, error) { - return nil, nil -} - -func (u *nullWorkflowRegistrySyncer) Ready() error { - return nil -} - -func (u *nullWorkflowRegistrySyncer) HealthReport() map[string]error { - return nil -} - -func (u *nullWorkflowRegistrySyncer) Name() string { - return "Null" + name -} diff --git a/core/services/workflows/syncer/workflow_registry_test.go b/core/services/workflows/syncer/workflow_registry_test.go index 58dcbed1022..8a7c3bb0a7c 100644 --- a/core/services/workflows/syncer/workflow_registry_test.go +++ b/core/services/workflows/syncer/workflow_registry_test.go @@ -3,10 +3,14 @@ package syncer import ( "context" "encoding/hex" - "strconv" "testing" "time" + "github.com/stretchr/testify/mock" + + "github.com/jonboulle/clockwork" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/custmsg" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" types "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -16,21 +20,29 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" "github.com/smartcontractkit/chainlink/v2/core/utils/matches" "github.com/stretchr/testify/require" ) +type testDonNotifier struct { + don capabilities.DON + err error +} + +func (t *testDonNotifier) WaitForDon(ctx context.Context) (capabilities.DON, error) { + return t.don, t.err +} + func Test_Workflow_Registry_Syncer(t *testing.T) { var ( - giveContents = "contents" - wantContents = "updated contents" - giveCfg = ContractEventPollerConfig{ - ContractName: ContractName, - ContractAddress: "0xdeadbeef", - StartBlockNum: 0, - QueryCount: 20, + giveContents = "contents" + wantContents = "updated contents" + contractAddress = "0xdeadbeef" + giveCfg = WorkflowEventPollerConfig{ + QueryCount: 20, } giveURL = "http://example.com" giveHash, err = crypto.Keccak256([]byte(giveURL)) @@ -57,7 +69,26 @@ func Test_Workflow_Registry_Syncer(t *testing.T) { return []byte(wantContents), nil } ticker = make(chan time.Time) - worker = NewWorkflowRegistry(lggr, orm, reader, gateway, giveCfg.ContractAddress, nil, nil, emitter, WithTicker(ticker)) + + handler = NewEventHandler(lggr, orm, gateway, nil, nil, + emitter, clockwork.NewFakeClock(), workflowkey.Key{}) + loader = NewWorkflowRegistryContractLoader(lggr, contractAddress, func(ctx context.Context, bytes []byte) (ContractReader, error) { + return reader, nil + }, handler) + + worker = NewWorkflowRegistry(lggr, func(ctx context.Context, bytes []byte) (ContractReader, error) { + return reader, nil + }, contractAddress, + WorkflowEventPollerConfig{ + QueryCount: 20, + }, handler, loader, + &testDonNotifier{ + don: capabilities.DON{ + ID: 1, + }, + err: nil, + }, + WithTicker(ticker)) ) // Cleanup the worker @@ -71,14 +102,14 @@ func Test_Workflow_Registry_Syncer(t *testing.T) { reader.EXPECT().QueryKey( matches.AnyContext, types.BoundContract{ - Name: giveCfg.ContractName, - Address: giveCfg.ContractAddress, + Name: WorkflowRegistryContractName, + Address: contractAddress, }, query.KeyFilter{ Key: string(ForceUpdateSecretsEvent), Expressions: []query.Expression{ query.Confidence(primitives.Finalized), - query.Block(strconv.FormatUint(giveCfg.StartBlockNum, 10), primitives.Gte), + query.Block("0", primitives.Gt), }, }, query.LimitAndSort{ @@ -87,6 +118,10 @@ func Test_Workflow_Registry_Syncer(t *testing.T) { }, new(values.Value), ).Return([]types.Sequence{giveLog}, nil) + reader.EXPECT().GetLatestValueWithHeadData(mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&types.Head{ + Height: "0", + }, nil) + reader.EXPECT().Bind(mock.Anything, mock.Anything).Return(nil) // Go run the worker servicetest.Run(t, worker) diff --git a/core/store/migrate/migrate.go b/core/store/migrate/migrate.go index 7c3d3deaaf0..c8d4a0e9621 100644 --- a/core/store/migrate/migrate.go +++ b/core/store/migrate/migrate.go @@ -105,8 +105,6 @@ func ensureMigrated(ctx context.Context, db *sql.DB, p *goose.Provider, provider } // insert records for existing migrations - //nolint - sql := fmt.Sprintf(`INSERT INTO %s (version_id, is_applied) VALUES ($1, true);`, providerTableName) return sqlutil.TransactDataSource(ctx, sqlxDB, nil, func(tx sqlutil.DataSource) error { for _, name := range names { diff --git a/core/store/migrate/migrations/0036_external_job_id.go b/core/store/migrate/migrations/0036_external_job_id.go index e8012da5e78..47442124a33 100644 --- a/core/store/migrate/migrations/0036_external_job_id.go +++ b/core/store/migrate/migrations/0036_external_job_id.go @@ -31,7 +31,6 @@ const ( ` ) -// nolint func Up36(ctx context.Context, tx *sql.Tx) error { // Add the external ID column and remove type specific ones. if _, err := tx.ExecContext(ctx, up36_1); err != nil { @@ -68,7 +67,6 @@ func Up36(ctx context.Context, tx *sql.Tx) error { return nil } -// nolint func Down36(ctx context.Context, tx *sql.Tx) error { if _, err := tx.ExecContext(ctx, down36); err != nil { return err diff --git a/core/store/migrate/migrations/0054_remove_legacy_pipeline.go b/core/store/migrate/migrations/0054_remove_legacy_pipeline.go index 6d3cb20b73d..fb4c473bdb2 100644 --- a/core/store/migrate/migrations/0054_remove_legacy_pipeline.go +++ b/core/store/migrate/migrations/0054_remove_legacy_pipeline.go @@ -32,7 +32,6 @@ type queryer interface { QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row } -// nolint func Up54(ctx context.Context, tx *sql.Tx) error { if err := CheckNoLegacyJobs(ctx, tx); err != nil { return err @@ -43,7 +42,6 @@ func Up54(ctx context.Context, tx *sql.Tx) error { return nil } -// nolint func Down54(ctx context.Context, tx *sql.Tx) error { return errors.New("irreversible migration") } diff --git a/core/store/migrate/migrations/0056_multichain.go b/core/store/migrate/migrations/0056_multichain.go index c56ff0397f1..39d7ec70b2b 100644 --- a/core/store/migrate/migrations/0056_multichain.go +++ b/core/store/migrate/migrations/0056_multichain.go @@ -44,7 +44,6 @@ DROP TABLE nodes; DROP TABLE evm_chains; ` -// nolint func Up56(ctx context.Context, tx *sql.Tx) error { if _, err := tx.ExecContext(ctx, up56); err != nil { return err @@ -71,7 +70,6 @@ func Up56(ctx context.Context, tx *sql.Tx) error { return nil } -// nolint func Down56(ctx context.Context, tx *sql.Tx) error { _, err := tx.ExecContext(ctx, down56) if err != nil { diff --git a/core/store/migrate/migrations/0195_add_not_null_to_evm_chain_id_in_job_specs.go b/core/store/migrate/migrations/0195_add_not_null_to_evm_chain_id_in_job_specs.go index a2ecb50a1c9..a689cd750eb 100644 --- a/core/store/migrate/migrations/0195_add_not_null_to_evm_chain_id_in_job_specs.go +++ b/core/store/migrate/migrations/0195_add_not_null_to_evm_chain_id_in_job_specs.go @@ -33,7 +33,6 @@ const ( ` ) -// nolint func Up195(ctx context.Context, tx *sql.Tx) error { chainID, set := os.LookupEnv(env.EVMChainIDNotNullMigration0195) if set { @@ -58,7 +57,6 @@ func Up195(ctx context.Context, tx *sql.Tx) error { return errors.Wrap(err, "failed to add null constraints") } -// nolint func Down195(ctx context.Context, tx *sql.Tx) error { if _, err := tx.ExecContext(ctx, dropNullConstraintsFromSpecs); err != nil { return err diff --git a/core/utils/big_math/big_math.go b/core/utils/big_math/big_math.go index a82621b92f5..013991480ca 100644 --- a/core/utils/big_math/big_math.go +++ b/core/utils/big_math/big_math.go @@ -58,7 +58,6 @@ func Accumulate(s []*big.Int) (r *big.Int) { return } -// nolint var ( Zero = big.NewInt(0) One = big.NewInt(1) diff --git a/core/utils/files.go b/core/utils/files.go index 71b52a0ea0a..9736e1f6926 100644 --- a/core/utils/files.go +++ b/core/utils/files.go @@ -104,7 +104,6 @@ func EnsureFilepathMaxPerms(filepath string, perms os.FileMode) (err error) { // FileSize repesents a file size in bytes. type FileSize uint64 -// nolint const ( KB = 1000 MB = 1000 * KB diff --git a/core/utils/utils.go b/core/utils/utils.go index 7ac97fabb21..98c2607baff 100644 --- a/core/utils/utils.go +++ b/core/utils/utils.go @@ -595,8 +595,6 @@ func (eb *ErrorBuffer) SetCap(cap int) { } // UnwrapError returns a list of underlying errors if passed error implements joinedError or return the err in a single-element list otherwise. -// -//nolint:errorlint // error type checks will fail on wrapped errors. Disabled since we are not doing checks on error types. func UnwrapError(err error) []error { joined, ok := err.(interface{ Unwrap() []error }) if !ok { diff --git a/core/web/middleware.go b/core/web/middleware.go index 6e9378e618f..aacb912dca7 100644 --- a/core/web/middleware.go +++ b/core/web/middleware.go @@ -2,7 +2,6 @@ package web import ( "embed" - "errors" "fmt" "io/fs" "net/http" @@ -40,7 +39,7 @@ const ( // ServeFileSystem wraps a http.FileSystem with an additional file existence check type ServeFileSystem interface { http.FileSystem - Exists(prefix string, path string) bool + Exists(prefix string, path string) (bool, error) } // EmbedFileSystem implements the ServeFileSystem interface using an embed.FS @@ -60,23 +59,19 @@ func NewEmbedFileSystem(efs embed.FS, pathPrefix string) ServeFileSystem { } // Exists implements the ServeFileSystem interface. -func (e *EmbedFileSystem) Exists(prefix string, filepath string) bool { - found := false +func (e *EmbedFileSystem) Exists(prefix string, filepath string) (found bool, err error) { if p := path.Base(strings.TrimPrefix(filepath, prefix)); len(p) < len(filepath) { - //nolint:errcheck - fs.WalkDir(e.FS, ".", func(fpath string, d fs.DirEntry, err error) error { + err = fs.WalkDir(e.FS, ".", func(fpath string, d fs.DirEntry, err error) error { fileName := path.Base(fpath) if fileName == p { found = true - // Return an error so that we terminate the search early. - // Otherwise, the search will continue for the rest of the file tree. - return errors.New("file found") + return fs.SkipAll } return nil }) } - return found + return } // Open implements the http.FileSystem interface. @@ -147,7 +142,9 @@ func (f *gzipFileHandler) findBestFile(w http.ResponseWriter, r *http.Request, f ext := extensionForEncoding(posenc) fname := fpath + ext - if f.root.Exists("/", fname) { + if ok, err := f.root.Exists("/", fname); err != nil { + return nil, nil, err + } else if ok { available = append(available, posenc) } } @@ -230,7 +227,10 @@ func ServeGzippedAssets(urlPrefix string, fs ServeFileSystem, lggr logger.Logger fileserver = http.StripPrefix(urlPrefix, fileserver) } return func(c *gin.Context) { - if fs.Exists(urlPrefix, c.Request.URL.Path) { + if ok, err := fs.Exists(urlPrefix, c.Request.URL.Path); err != nil { + lggr.Errorw("Failed to search for file", "err", err) + c.AbortWithStatus(http.StatusInternalServerError) + } else if ok { fileserver.ServeHTTP(c.Writer, c.Request) c.Abort() } else { diff --git a/core/web/testutils/mock_relayer.go b/core/web/testutils/mock_relayer.go index 4666f9da6a4..c96bf5ee494 100644 --- a/core/web/testutils/mock_relayer.go +++ b/core/web/testutils/mock_relayer.go @@ -33,7 +33,7 @@ func (m MockRelayer) HealthReport() map[string]error { panic("not implemented") } -func (m MockRelayer) NewChainWriter(_ context.Context, _ []byte) (commontypes.ChainWriter, error) { +func (m MockRelayer) NewContractWriter(_ context.Context, _ []byte) (commontypes.ContractWriter, error) { panic("not implemented") } diff --git a/deployment/address_book.go b/deployment/address_book.go index 3125313a841..6f605013011 100644 --- a/deployment/address_book.go +++ b/deployment/address_book.go @@ -27,6 +27,7 @@ var ( Version1_1_0 = *semver.MustParse("1.1.0") Version1_2_0 = *semver.MustParse("1.2.0") Version1_5_0 = *semver.MustParse("1.5.0") + Version1_5_1 = *semver.MustParse("1.5.1") Version1_6_0_dev = *semver.MustParse("1.6.0-dev") ) @@ -255,3 +256,41 @@ func SearchAddressBook(ab AddressBook, chain uint64, typ ContractType) (string, return "", fmt.Errorf("not found") } + +func AddressBookContains(ab AddressBook, chain uint64, addrToFind string) (bool, error) { + addrs, err := ab.AddressesForChain(chain) + if err != nil { + return false, err + } + + for addr := range addrs { + if addr == addrToFind { + return true, nil + } + } + + return false, nil +} + +// AddressesContainBundle checks if the addresses +// contains a single instance of all the addresses in the bundle. +// It returns an error if there are more than one instance of a contract. +func AddressesContainBundle(addrs map[string]TypeAndVersion, wantTypes map[TypeAndVersion]struct{}) (bool, error) { + counts := make(map[TypeAndVersion]int) + for wantType := range wantTypes { + for _, haveType := range addrs { + if wantType == haveType { + counts[wantType]++ + if counts[wantType] > 1 { + return false, fmt.Errorf("found more than one instance of contract %s", wantType) + } + } + } + } + // Either 0 or 1, so we can just check the sum. + sum := 0 + for _, count := range counts { + sum += count + } + return sum == len(wantTypes), nil +} diff --git a/deployment/address_book_test.go b/deployment/address_book_test.go index 35efdbf8546..e022e89a9ab 100644 --- a/deployment/address_book_test.go +++ b/deployment/address_book_test.go @@ -243,3 +243,36 @@ func TestAddressBook_ConcurrencyAndDeadlock(t *testing.T) { wg.Wait() } + +func TestAddressesContainsBundle(t *testing.T) { + onRamp100 := NewTypeAndVersion("OnRamp", Version1_0_0) + onRamp110 := NewTypeAndVersion("OnRamp", Version1_1_0) + onRamp120 := NewTypeAndVersion("OnRamp", Version1_2_0) + addr1 := common.HexToAddress("0x1").String() + addr2 := common.HexToAddress("0x2").String() + addr3 := common.HexToAddress("0x3").String() + + // More than one instance should error + _, err := AddressesContainBundle(map[string]TypeAndVersion{ + addr1: onRamp100, + addr2: onRamp100, + }, map[TypeAndVersion]struct{}{onRamp100: {}}) + require.Error(t, err) + + // No such instances should be false + exists, err := AddressesContainBundle(map[string]TypeAndVersion{ + addr2: onRamp110, + addr1: onRamp110, + }, map[TypeAndVersion]struct{}{onRamp100: {}}) + require.NoError(t, err) + assert.Equal(t, exists, false) + + // 2 elements + exists, err = AddressesContainBundle(map[string]TypeAndVersion{ + addr1: onRamp100, + addr2: onRamp110, + addr3: onRamp120, + }, map[TypeAndVersion]struct{}{onRamp100: {}, onRamp110: {}}) + require.NoError(t, err) + assert.Equal(t, exists, true) +} diff --git a/deployment/ccip/changeset/accept_ownership_test.go b/deployment/ccip/changeset/accept_ownership_test.go new file mode 100644 index 00000000000..796db6aed09 --- /dev/null +++ b/deployment/ccip/changeset/accept_ownership_test.go @@ -0,0 +1,125 @@ +package changeset + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func Test_NewAcceptOwnershipChangeset(t *testing.T) { + e := NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + NumOfUsersPerChain: 1, + Nodes: 4, + Bootstraps: 1, + }, &TestConfigs{}) + state, err := LoadOnchainState(e.Env) + require.NoError(t, err) + + allChains := maps.Keys(e.Env.Chains) + source := allChains[0] + dest := allChains[1] + + timelocks := map[uint64]*gethwrappers.RBACTimelock{ + source: state.Chains[source].Timelock, + dest: state.Chains[dest].Timelock, + } + + // at this point we have the initial deploys done, now we need to transfer ownership + // to the timelock contract + state, err = LoadOnchainState(e.Env) + require.NoError(t, err) + + // compose the transfer ownership and accept ownership changesets + _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocks, []commonchangeset.ChangesetApplication{ + // note this doesn't have proposals. + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), + Config: genTestTransferOwnershipConfig(e, allChains, state), + }, + }) + require.NoError(t, err) + + assertTimelockOwnership(t, e, allChains, state) +} + +func genTestTransferOwnershipConfig( + e DeployedEnv, + chains []uint64, + state CCIPOnChainState, +) commonchangeset.TransferToMCMSWithTimelockConfig { + var ( + timelocksPerChain = make(map[uint64]common.Address) + contracts = make(map[uint64][]common.Address) + ) + + // chain contracts + for _, chain := range chains { + timelocksPerChain[chain] = state.Chains[chain].Timelock.Address() + contracts[chain] = []common.Address{ + state.Chains[chain].OnRamp.Address(), + state.Chains[chain].OffRamp.Address(), + state.Chains[chain].FeeQuoter.Address(), + state.Chains[chain].NonceManager.Address(), + state.Chains[chain].RMNRemote.Address(), + } + } + + // home chain + homeChainTimelockAddress := state.Chains[e.HomeChainSel].Timelock.Address() + timelocksPerChain[e.HomeChainSel] = homeChainTimelockAddress + contracts[e.HomeChainSel] = append(contracts[e.HomeChainSel], + state.Chains[e.HomeChainSel].CapabilityRegistry.Address(), + state.Chains[e.HomeChainSel].CCIPHome.Address(), + state.Chains[e.HomeChainSel].RMNHome.Address(), + ) + + return commonchangeset.TransferToMCMSWithTimelockConfig{ + ContractsByChain: contracts, + } +} + +// assertTimelockOwnership asserts that the ownership of the contracts has been transferred +// to the appropriate timelock contract on each chain. +func assertTimelockOwnership( + t *testing.T, + e DeployedEnv, + chains []uint64, + state CCIPOnChainState, +) { + // check that the ownership has been transferred correctly + for _, chain := range chains { + for _, contract := range []common.Address{ + state.Chains[chain].OnRamp.Address(), + state.Chains[chain].OffRamp.Address(), + state.Chains[chain].FeeQuoter.Address(), + state.Chains[chain].NonceManager.Address(), + state.Chains[chain].RMNRemote.Address(), + } { + owner, _, err := commonchangeset.LoadOwnableContract(contract, e.Env.Chains[chain].Client) + require.NoError(t, err) + require.Equal(t, state.Chains[chain].Timelock.Address(), owner) + } + } + + // check home chain contracts ownership + homeChainTimelockAddress := state.Chains[e.HomeChainSel].Timelock.Address() + for _, contract := range []common.Address{ + state.Chains[e.HomeChainSel].CapabilityRegistry.Address(), + state.Chains[e.HomeChainSel].CCIPHome.Address(), + state.Chains[e.HomeChainSel].RMNHome.Address(), + } { + owner, _, err := commonchangeset.LoadOwnableContract(contract, e.Env.Chains[e.HomeChainSel].Client) + require.NoError(t, err) + require.Equal(t, homeChainTimelockAddress, owner) + } +} diff --git a/deployment/ccip/changeset/active_candidate.go b/deployment/ccip/changeset/active_candidate.go deleted file mode 100644 index bc2ac2a208c..00000000000 --- a/deployment/ccip/changeset/active_candidate.go +++ /dev/null @@ -1,102 +0,0 @@ -package changeset - -import ( - "fmt" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" -) - -// PromoteAllCandidatesChangeset generates a proposal to call promoteCandidate on the CCIPHome through CapReg. -// This needs to be called after SetCandidateProposal is executed. -func PromoteAllCandidatesChangeset( - state CCIPOnChainState, - homeChainSel, newChainSel uint64, - nodes deployment.Nodes, -) (deployment.ChangesetOutput, error) { - promoteCandidateOps, err := PromoteAllCandidatesForChainOps( - state.Chains[homeChainSel].CapabilityRegistry, - state.Chains[homeChainSel].CCIPHome, - newChainSel, - nodes.NonBootstraps(), - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - prop, err := BuildProposalFromBatches(state, []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(homeChainSel), - Batch: promoteCandidateOps, - }}, "promoteCandidate for commit and execution", 0) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{ - *prop, - }, - }, nil -} - -// SetCandidateExecPluginProposal calls setCandidate on the CCIPHome for setting up OCR3 exec Plugin config for the new chain. -func SetCandidatePluginChangeset( - state CCIPOnChainState, - e deployment.Environment, - nodes deployment.Nodes, - ocrSecrets deployment.OCRSecrets, - homeChainSel, feedChainSel, newChainSel uint64, - tokenConfig TokenConfig, - pluginType cctypes.PluginType, -) (deployment.ChangesetOutput, error) { - ccipOCRParams := DefaultOCRParams( - feedChainSel, - tokenConfig.GetTokenInfo(e.Logger, state.Chains[newChainSel].LinkToken, state.Chains[newChainSel].Weth9), - ) - newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( - ocrSecrets, - state.Chains[newChainSel].OffRamp, - e.Chains[newChainSel], - nodes.NonBootstraps(), - state.Chains[homeChainSel].RMNHome.Address(), - ccipOCRParams.OCRParameters, - ccipOCRParams.CommitOffChainConfig, - ccipOCRParams.ExecuteOffChainConfig, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - execConfig, ok := newDONArgs[pluginType] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("missing exec plugin in ocr3Configs") - } - - setCandidateMCMSOps, err := SetCandidateOnExistingDon( - execConfig, - state.Chains[homeChainSel].CapabilityRegistry, - state.Chains[homeChainSel].CCIPHome, - newChainSel, - nodes.NonBootstraps(), - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - prop, err := BuildProposalFromBatches(state, []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(homeChainSel), - Batch: setCandidateMCMSOps, - }}, "SetCandidate for execution", 0) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{ - *prop, - }, - }, nil - -} diff --git a/deployment/ccip/changeset/active_candidate_helpers.go b/deployment/ccip/changeset/active_candidate_helpers.go deleted file mode 100644 index aea488c36b2..00000000000 --- a/deployment/ccip/changeset/active_candidate_helpers.go +++ /dev/null @@ -1,142 +0,0 @@ -package changeset - -import ( - "fmt" - "math/big" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" -) - -// SetCandidateExecPluginOps calls setCandidate on CCIPHome contract through the UpdateDON call on CapReg contract -// This proposes to set up OCR3 config for the provided plugin for the DON -func SetCandidateOnExistingDon( - pluginConfig ccip_home.CCIPHomeOCR3Config, - capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, - chainSelector uint64, - nodes deployment.Nodes, -) ([]mcms.Operation, error) { - // fetch DON ID for the chain - donID, err := internal.DonIDForChain(capReg, ccipHome, chainSelector) - if err != nil { - return nil, fmt.Errorf("fetch don id for chain: %w", err) - } - fmt.Printf("donID: %d", donID) - encodedSetCandidateCall, err := internal.CCIPHomeABI.Pack( - "setCandidate", - donID, - pluginConfig.PluginType, - pluginConfig, - [32]byte{}, - ) - if err != nil { - return nil, fmt.Errorf("pack set candidate call: %w", err) - } - - // set candidate call - updateDonTx, err := capReg.UpdateDON( - deployment.SimTransactOpts(), - donID, - nodes.PeerIDs(), - []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: internal.CCIPCapabilityID, - Config: encodedSetCandidateCall, - }, - }, - false, - nodes.DefaultF(), - ) - if err != nil { - return nil, fmt.Errorf("update don w/ exec config: %w", err) - } - - return []mcms.Operation{{ - To: capReg.Address(), - Data: updateDonTx.Data(), - Value: big.NewInt(0), - }}, nil -} - -// PromoteCandidateOp will create the MCMS Operation for `promoteCandidateAndRevokeActive` directed towards the capabilityRegistry -func PromoteCandidateOp(donID uint32, pluginType uint8, capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, nodes deployment.Nodes) (mcms.Operation, error) { - - allConfigs, err := ccipHome.GetAllConfigs(nil, donID, pluginType) - if err != nil { - return mcms.Operation{}, err - } - - if allConfigs.CandidateConfig.ConfigDigest == [32]byte{} { - return mcms.Operation{}, fmt.Errorf("candidate digest is empty, expected nonempty") - } - fmt.Printf("commit candidate digest after setCandidate: %x\n", allConfigs.CandidateConfig.ConfigDigest) - - encodedPromotionCall, err := internal.CCIPHomeABI.Pack( - "promoteCandidateAndRevokeActive", - donID, - pluginType, - allConfigs.CandidateConfig.ConfigDigest, - allConfigs.ActiveConfig.ConfigDigest, - ) - if err != nil { - return mcms.Operation{}, fmt.Errorf("pack promotion call: %w", err) - } - - updateDonTx, err := capReg.UpdateDON( - deployment.SimTransactOpts(), - donID, - nodes.PeerIDs(), - []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: internal.CCIPCapabilityID, - Config: encodedPromotionCall, - }, - }, - false, - nodes.DefaultF(), - ) - if err != nil { - return mcms.Operation{}, fmt.Errorf("error creating updateDon op for donID(%d) and plugin type (%d): %w", donID, pluginType, err) - } - return mcms.Operation{ - To: capReg.Address(), - Data: updateDonTx.Data(), - Value: big.NewInt(0), - }, nil -} - -// PromoteAllCandidatesForChainOps promotes the candidate commit and exec configs to active by calling promoteCandidateAndRevokeActive on CCIPHome through the UpdateDON call on CapReg contract -func PromoteAllCandidatesForChainOps( - capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, - chainSelector uint64, - nodes deployment.Nodes, -) ([]mcms.Operation, error) { - // fetch DON ID for the chain - donID, err := internal.DonIDForChain(capReg, ccipHome, chainSelector) - if err != nil { - return nil, fmt.Errorf("fetch don id for chain: %w", err) - } - - var mcmsOps []mcms.Operation - updateCommitOp, err := PromoteCandidateOp(donID, uint8(cctypes.PluginTypeCCIPCommit), capReg, ccipHome, nodes) - if err != nil { - return nil, fmt.Errorf("promote candidate op: %w", err) - } - mcmsOps = append(mcmsOps, updateCommitOp) - - updateExecOp, err := PromoteCandidateOp(donID, uint8(cctypes.PluginTypeCCIPExec), capReg, ccipHome, nodes) - if err != nil { - return nil, fmt.Errorf("promote candidate op: %w", err) - } - mcmsOps = append(mcmsOps, updateExecOp) - - return mcmsOps, nil -} diff --git a/deployment/ccip/changeset/add_chain.go b/deployment/ccip/changeset/add_chain.go deleted file mode 100644 index b129fefaea0..00000000000 --- a/deployment/ccip/changeset/add_chain.go +++ /dev/null @@ -1,147 +0,0 @@ -package changeset - -import ( - "fmt" - "math/big" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" -) - -// NewChainInboundChangeset generates a proposal -// to connect the new chain to the existing chains. -func NewChainInboundChangeset( - e deployment.Environment, - state CCIPOnChainState, - homeChainSel uint64, - newChainSel uint64, - sources []uint64, -) (deployment.ChangesetOutput, error) { - // Generate proposal which enables new destination (from test router) on all source chains. - var batches []timelock.BatchChainOperation - for _, source := range sources { - enableOnRampDest, err := state.Chains[source].OnRamp.ApplyDestChainConfigUpdates(deployment.SimTransactOpts(), []onramp.OnRampDestChainConfigArgs{ - { - DestChainSelector: newChainSel, - Router: state.Chains[source].TestRouter.Address(), - }, - }) - if err != nil { - return deployment.ChangesetOutput{}, err - } - enableFeeQuoterDest, err := state.Chains[source].FeeQuoter.ApplyDestChainConfigUpdates( - deployment.SimTransactOpts(), - []fee_quoter.FeeQuoterDestChainConfigArgs{ - { - DestChainSelector: newChainSel, - DestChainConfig: DefaultFeeQuoterDestChainConfig(), - }, - }) - if err != nil { - return deployment.ChangesetOutput{}, err - } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(source), - Batch: []mcms.Operation{ - { - // Enable the source in on ramp - To: state.Chains[source].OnRamp.Address(), - Data: enableOnRampDest.Data(), - Value: big.NewInt(0), - }, - { - To: state.Chains[source].FeeQuoter.Address(), - Data: enableFeeQuoterDest.Data(), - Value: big.NewInt(0), - }, - }, - }) - } - - addChainOp, err := ApplyChainConfigUpdatesOp(e, state, homeChainSel, []uint64{newChainSel}) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(homeChainSel), - Batch: []mcms.Operation{ - addChainOp, - }, - }) - - prop, err := BuildProposalFromBatches(state, batches, "proposal to set new chains", 0) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*prop}, - }, nil -} - -// AddDonAndSetCandidateChangeset adds new DON for destination to home chain -// and sets the commit plugin config as candidateConfig for the don. -func AddDonAndSetCandidateChangeset( - state CCIPOnChainState, - e deployment.Environment, - nodes deployment.Nodes, - ocrSecrets deployment.OCRSecrets, - homeChainSel, feedChainSel, newChainSel uint64, - tokenConfig TokenConfig, - pluginType types.PluginType, -) (deployment.ChangesetOutput, error) { - ccipOCRParams := DefaultOCRParams( - feedChainSel, - tokenConfig.GetTokenInfo(e.Logger, state.Chains[newChainSel].LinkToken, state.Chains[newChainSel].Weth9), - ) - newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( - ocrSecrets, - state.Chains[newChainSel].OffRamp, - e.Chains[newChainSel], - nodes.NonBootstraps(), - state.Chains[homeChainSel].RMNHome.Address(), - ccipOCRParams.OCRParameters, - ccipOCRParams.CommitOffChainConfig, - ccipOCRParams.ExecuteOffChainConfig, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - latestDon, err := internal.LatestCCIPDON(state.Chains[homeChainSel].CapabilityRegistry) - if err != nil { - return deployment.ChangesetOutput{}, err - } - commitConfig, ok := newDONArgs[pluginType] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("missing commit plugin in ocr3Configs") - } - donID := latestDon.Id + 1 - addDonOp, err := NewDonWithCandidateOp( - donID, commitConfig, - state.Chains[homeChainSel].CapabilityRegistry, - nodes.NonBootstraps(), - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - prop, err := BuildProposalFromBatches(state, []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(homeChainSel), - Batch: []mcms.Operation{addDonOp}, - }}, "setCandidate for commit and AddDon on new Chain", 0) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*prop}, - }, nil -} diff --git a/deployment/ccip/changeset/consts.go b/deployment/ccip/changeset/consts.go deleted file mode 100644 index 8d5e64ccde7..00000000000 --- a/deployment/ccip/changeset/consts.go +++ /dev/null @@ -1,11 +0,0 @@ -package changeset - -type TokenSymbol string - -const ( - LinkSymbol TokenSymbol = "LINK" - WethSymbol TokenSymbol = "WETH" - USDCSymbol TokenSymbol = "USDC" - LinkDecimals = 18 - WethDecimals = 18 -) diff --git a/deployment/ccip/changeset/cs_active_candidate.go b/deployment/ccip/changeset/cs_active_candidate.go new file mode 100644 index 00000000000..ecd87e2d399 --- /dev/null +++ b/deployment/ccip/changeset/cs_active_candidate.go @@ -0,0 +1,323 @@ +package changeset + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +) + +var ( + _ deployment.ChangeSet[PromoteAllCandidatesChangesetConfig] = PromoteAllCandidatesChangeset + _ deployment.ChangeSet[AddDonAndSetCandidateChangesetConfig] = SetCandidatePluginChangeset +) + +type PromoteAllCandidatesChangesetConfig struct { + HomeChainSelector uint64 + NewChainSelector uint64 + NodeIDs []string +} + +func (p PromoteAllCandidatesChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) (deployment.Nodes, error) { + if p.HomeChainSelector == 0 { + return nil, fmt.Errorf("HomeChainSelector must be set") + } + if p.NewChainSelector == 0 { + return nil, fmt.Errorf("NewChainSelector must be set") + } + if len(p.NodeIDs) == 0 { + return nil, fmt.Errorf("NodeIDs must be set") + } + + nodes, err := deployment.NodeInfo(p.NodeIDs, e.Offchain) + if err != nil { + return nil, fmt.Errorf("fetch node info: %w", err) + } + + donID, err := internal.DonIDForChain( + state.Chains[p.HomeChainSelector].CapabilityRegistry, + state.Chains[p.HomeChainSelector].CCIPHome, + p.NewChainSelector, + ) + if err != nil { + return nil, fmt.Errorf("fetch don id for chain: %w", err) + } + + // check if the DON ID has a candidate digest set that we can promote + for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { + candidateDigest, err := state.Chains[p.HomeChainSelector].CCIPHome.GetCandidateDigest(nil, donID, uint8(pluginType)) + if err != nil { + return nil, fmt.Errorf("error fetching candidate digest for pluginType(%s): %w", pluginType.String(), err) + } + if candidateDigest == [32]byte{} { + return nil, fmt.Errorf("candidate digest is zero, must be non-zero to promote") + } + } + + return nodes, nil +} + +// PromoteAllCandidatesChangeset generates a proposal to call promoteCandidate on the CCIPHome through CapReg. +// This needs to be called after SetCandidateProposal is executed. +func PromoteAllCandidatesChangeset( + e deployment.Environment, + cfg PromoteAllCandidatesChangesetConfig, +) (deployment.ChangesetOutput, error) { + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + nodes, err := cfg.Validate(e, state) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) + } + + promoteCandidateOps, err := promoteAllCandidatesForChainOps( + state.Chains[cfg.HomeChainSelector].CapabilityRegistry, + state.Chains[cfg.HomeChainSelector].CCIPHome, + cfg.NewChainSelector, + nodes.NonBootstraps(), + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + var ( + timelocksPerChain = map[uint64]common.Address{ + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), + } + proposerMCMSes = map[uint64]*gethwrappers.ManyChainMultiSig{ + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, + } + ) + prop, err := proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), + Batch: promoteCandidateOps, + }}, + "promoteCandidate for commit and execution", + 0, // minDelay + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{ + *prop, + }, + }, nil +} + +// SetCandidatePluginChangeset calls setCandidate on the CCIPHome for setting up OCR3 exec Plugin config for the new chain. +func SetCandidatePluginChangeset( + e deployment.Environment, + cfg AddDonAndSetCandidateChangesetConfig, +) (deployment.ChangesetOutput, error) { + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + nodes, err := cfg.Validate(e, state) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) + } + + newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( + e.OCRSecrets, + state.Chains[cfg.NewChainSelector].OffRamp, + e.Chains[cfg.NewChainSelector], + nodes.NonBootstraps(), + state.Chains[cfg.HomeChainSelector].RMNHome.Address(), + cfg.CCIPOCRParams.OCRParameters, + cfg.CCIPOCRParams.CommitOffChainConfig, + cfg.CCIPOCRParams.ExecuteOffChainConfig, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + config, ok := newDONArgs[cfg.PluginType] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("missing %s plugin in ocr3Configs", cfg.PluginType.String()) + } + + setCandidateMCMSOps, err := setCandidateOnExistingDon( + config, + state.Chains[cfg.HomeChainSelector].CapabilityRegistry, + state.Chains[cfg.HomeChainSelector].CCIPHome, + cfg.NewChainSelector, + nodes.NonBootstraps(), + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + var ( + timelocksPerChain = map[uint64]common.Address{ + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), + } + proposerMCMSes = map[uint64]*gethwrappers.ManyChainMultiSig{ + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, + } + ) + prop, err := proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), + Batch: setCandidateMCMSOps, + }}, + fmt.Sprintf("SetCandidate for %s plugin", cfg.PluginType.String()), + 0, // minDelay + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{ + *prop, + }, + }, nil +} + +// setCandidateOnExistingDon calls setCandidate on CCIPHome contract through the UpdateDON call on CapReg contract +// This proposes to set up OCR3 config for the provided plugin for the DON +func setCandidateOnExistingDon( + pluginConfig ccip_home.CCIPHomeOCR3Config, + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + chainSelector uint64, + nodes deployment.Nodes, +) ([]mcms.Operation, error) { + // fetch DON ID for the chain + donID, err := internal.DonIDForChain(capReg, ccipHome, chainSelector) + if err != nil { + return nil, fmt.Errorf("fetch don id for chain: %w", err) + } + fmt.Printf("donID: %d", donID) + encodedSetCandidateCall, err := internal.CCIPHomeABI.Pack( + "setCandidate", + donID, + pluginConfig.PluginType, + pluginConfig, + [32]byte{}, + ) + if err != nil { + return nil, fmt.Errorf("pack set candidate call: %w", err) + } + + // set candidate call + updateDonTx, err := capReg.UpdateDON( + deployment.SimTransactOpts(), + donID, + nodes.PeerIDs(), + []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: internal.CCIPCapabilityID, + Config: encodedSetCandidateCall, + }, + }, + false, + nodes.DefaultF(), + ) + if err != nil { + return nil, fmt.Errorf("update don w/ exec config: %w", err) + } + + return []mcms.Operation{{ + To: capReg.Address(), + Data: updateDonTx.Data(), + Value: big.NewInt(0), + }}, nil +} + +// promoteCandidateOp will create the MCMS Operation for `promoteCandidateAndRevokeActive` directed towards the capabilityRegistry +func promoteCandidateOp(donID uint32, pluginType uint8, capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, nodes deployment.Nodes) (mcms.Operation, error) { + + allConfigs, err := ccipHome.GetAllConfigs(nil, donID, pluginType) + if err != nil { + return mcms.Operation{}, err + } + + if allConfigs.CandidateConfig.ConfigDigest == [32]byte{} { + return mcms.Operation{}, fmt.Errorf("candidate digest is empty, expected nonempty") + } + fmt.Printf("commit candidate digest after setCandidate: %x\n", allConfigs.CandidateConfig.ConfigDigest) + + encodedPromotionCall, err := internal.CCIPHomeABI.Pack( + "promoteCandidateAndRevokeActive", + donID, + pluginType, + allConfigs.CandidateConfig.ConfigDigest, + allConfigs.ActiveConfig.ConfigDigest, + ) + if err != nil { + return mcms.Operation{}, fmt.Errorf("pack promotion call: %w", err) + } + + updateDonTx, err := capReg.UpdateDON( + deployment.SimTransactOpts(), + donID, + nodes.PeerIDs(), + []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: internal.CCIPCapabilityID, + Config: encodedPromotionCall, + }, + }, + false, + nodes.DefaultF(), + ) + if err != nil { + return mcms.Operation{}, fmt.Errorf("error creating updateDon op for donID(%d) and plugin type (%d): %w", donID, pluginType, err) + } + return mcms.Operation{ + To: capReg.Address(), + Data: updateDonTx.Data(), + Value: big.NewInt(0), + }, nil +} + +// promoteAllCandidatesForChainOps promotes the candidate commit and exec configs to active by calling promoteCandidateAndRevokeActive on CCIPHome through the UpdateDON call on CapReg contract +func promoteAllCandidatesForChainOps( + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + chainSelector uint64, + nodes deployment.Nodes, +) ([]mcms.Operation, error) { + // fetch DON ID for the chain + donID, err := internal.DonIDForChain(capReg, ccipHome, chainSelector) + if err != nil { + return nil, fmt.Errorf("fetch don id for chain: %w", err) + } + + var mcmsOps []mcms.Operation + updateCommitOp, err := promoteCandidateOp(donID, uint8(cctypes.PluginTypeCCIPCommit), capReg, ccipHome, nodes) + if err != nil { + return nil, fmt.Errorf("promote candidate op: %w", err) + } + mcmsOps = append(mcmsOps, updateCommitOp) + + updateExecOp, err := promoteCandidateOp(donID, uint8(cctypes.PluginTypeCCIPExec), capReg, ccipHome, nodes) + if err != nil { + return nil, fmt.Errorf("promote candidate op: %w", err) + } + mcmsOps = append(mcmsOps, updateExecOp) + + return mcmsOps, nil +} diff --git a/deployment/ccip/changeset/active_candidate_test.go b/deployment/ccip/changeset/cs_active_candidate_test.go similarity index 81% rename from deployment/ccip/changeset/active_candidate_test.go rename to deployment/ccip/changeset/cs_active_candidate_test.go index baa051385e6..0fb29242794 100644 --- a/deployment/ccip/changeset/active_candidate_test.go +++ b/deployment/ccip/changeset/cs_active_candidate_test.go @@ -4,12 +4,15 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "golang.org/x/exp/maps" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -18,6 +21,7 @@ import ( "github.com/stretchr/testify/require" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -26,10 +30,16 @@ func TestActiveCandidate(t *testing.T) { t.Skipf("to be enabled after latest cl-ccip is compatible") lggr := logger.TestLogger(t) - tenv := NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 3, 5, nil) + tenv := NewMemoryEnvironmentWithJobsAndContracts(t, lggr, memory.MemoryEnvironmentConfig{ + Chains: 3, + NumOfUsersPerChain: 1, + Nodes: 5, + Bootstraps: 1, + }, nil) e := tenv.Env state, err := LoadOnchainState(tenv.Env) require.NoError(t, err) + allChains := maps.Keys(e.Chains) // Add all lanes require.NoError(t, AddLanesForAll(e, state)) @@ -80,14 +90,19 @@ func TestActiveCandidate(t *testing.T) { //Wait for all exec reports to land ConfirmExecWithSeqNrsForAll(t, e, state, expectedSeqNumExec, startBlocks) - // transfer ownership - TransferAllOwnership(t, state, tenv.HomeChainSel, e) - acceptOwnershipProposal, err := GenerateAcceptOwnershipProposal(state, tenv.HomeChainSel, e.AllChainSelectors()) - require.NoError(t, err) - acceptOwnershipExec := commonchangeset.SignProposal(t, e, acceptOwnershipProposal) - for _, sel := range e.AllChainSelectors() { - commonchangeset.ExecuteProposal(t, e, acceptOwnershipExec, state.Chains[sel].Timelock, sel) + // compose the transfer ownership and accept ownership changesets + timelocks := make(map[uint64]*gethwrappers.RBACTimelock) + for _, chain := range allChains { + timelocks[chain] = state.Chains[chain].Timelock } + _, err = commonchangeset.ApplyChangesets(t, e, timelocks, []commonchangeset.ChangesetApplication{ + // note this doesn't have proposals. + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), + Config: genTestTransferOwnershipConfig(tenv, allChains, state), + }, + }) + require.NoError(t, err) // Apply the accept ownership proposal to all the chains. err = ConfirmRequestOnSourceAndDest(t, e, state, tenv.HomeChainSel, tenv.FeedChainSel, 2) @@ -126,9 +141,10 @@ func TestActiveCandidate(t *testing.T) { ccipOCRParams := DefaultOCRParams( tenv.FeedChainSel, tokenConfig.GetTokenInfo(e.Logger, state.Chains[tenv.FeedChainSel].LinkToken, state.Chains[tenv.FeedChainSel].Weth9), + nil, ) ocr3ConfigMap, err := internal.BuildOCR3ConfigForCCIPHome( - deployment.XXXGenerateTestOCRSecrets(), + e.OCRSecrets, state.Chains[tenv.FeedChainSel].OffRamp, e.Chains[tenv.FeedChainSel], nodes.NonBootstraps(), @@ -139,7 +155,15 @@ func TestActiveCandidate(t *testing.T) { ) require.NoError(t, err) - setCommitCandidateOp, err := SetCandidateOnExistingDon( + var ( + timelocksPerChain = map[uint64]common.Address{ + tenv.HomeChainSel: state.Chains[tenv.HomeChainSel].Timelock.Address(), + } + proposerMCMSes = map[uint64]*gethwrappers.ManyChainMultiSig{ + tenv.HomeChainSel: state.Chains[tenv.HomeChainSel].ProposerMcm, + } + ) + setCommitCandidateOp, err := setCandidateOnExistingDon( ocr3ConfigMap[cctypes.PluginTypeCCIPCommit], state.Chains[tenv.HomeChainSel].CapabilityRegistry, state.Chains[tenv.HomeChainSel].CCIPHome, @@ -147,7 +171,7 @@ func TestActiveCandidate(t *testing.T) { nodes.NonBootstraps(), ) require.NoError(t, err) - setCommitCandidateProposal, err := BuildProposalFromBatches(state, []timelock.BatchChainOperation{{ + setCommitCandidateProposal, err := proposalutils.BuildProposalFromBatches(timelocksPerChain, proposerMCMSes, []timelock.BatchChainOperation{{ ChainIdentifier: mcms.ChainIdentifier(tenv.HomeChainSel), Batch: setCommitCandidateOp, }}, "set new candidates on commit plugin", 0) @@ -156,7 +180,7 @@ func TestActiveCandidate(t *testing.T) { commonchangeset.ExecuteProposal(t, e, setCommitCandidateSigned, state.Chains[tenv.HomeChainSel].Timelock, tenv.HomeChainSel) // create the op for the commit plugin as well - setExecCandidateOp, err := SetCandidateOnExistingDon( + setExecCandidateOp, err := setCandidateOnExistingDon( ocr3ConfigMap[cctypes.PluginTypeCCIPExec], state.Chains[tenv.HomeChainSel].CapabilityRegistry, state.Chains[tenv.HomeChainSel].CCIPHome, @@ -165,7 +189,7 @@ func TestActiveCandidate(t *testing.T) { ) require.NoError(t, err) - setExecCandidateProposal, err := BuildProposalFromBatches(state, []timelock.BatchChainOperation{{ + setExecCandidateProposal, err := proposalutils.BuildProposalFromBatches(timelocksPerChain, proposerMCMSes, []timelock.BatchChainOperation{{ ChainIdentifier: mcms.ChainIdentifier(tenv.HomeChainSel), Batch: setExecCandidateOp, }}, "set new candidates on commit and exec plugins", 0) @@ -190,9 +214,9 @@ func TestActiveCandidate(t *testing.T) { oldCandidateDigest, err := state.Chains[tenv.HomeChainSel].CCIPHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPExec)) require.NoError(t, err) - promoteOps, err := PromoteAllCandidatesForChainOps(state.Chains[tenv.HomeChainSel].CapabilityRegistry, state.Chains[tenv.HomeChainSel].CCIPHome, tenv.FeedChainSel, nodes.NonBootstraps()) + promoteOps, err := promoteAllCandidatesForChainOps(state.Chains[tenv.HomeChainSel].CapabilityRegistry, state.Chains[tenv.HomeChainSel].CCIPHome, tenv.FeedChainSel, nodes.NonBootstraps()) require.NoError(t, err) - promoteProposal, err := BuildProposalFromBatches(state, []timelock.BatchChainOperation{{ + promoteProposal, err := proposalutils.BuildProposalFromBatches(timelocksPerChain, proposerMCMSes, []timelock.BatchChainOperation{{ ChainIdentifier: mcms.ChainIdentifier(tenv.HomeChainSel), Batch: promoteOps, }}, "promote candidates and revoke actives", 0) diff --git a/deployment/ccip/changeset/cs_add_chain.go b/deployment/ccip/changeset/cs_add_chain.go new file mode 100644 index 00000000000..d589d16b779 --- /dev/null +++ b/deployment/ccip/changeset/cs_add_chain.go @@ -0,0 +1,348 @@ +package changeset + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-ccip/chainconfig" + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" +) + +var _ deployment.ChangeSet[ChainInboundChangesetConfig] = NewChainInboundChangeset + +type ChainInboundChangesetConfig struct { + HomeChainSelector uint64 + NewChainSelector uint64 + SourceChainSelectors []uint64 +} + +func (c ChainInboundChangesetConfig) Validate() error { + if c.HomeChainSelector == 0 { + return fmt.Errorf("HomeChainSelector must be set") + } + if c.NewChainSelector == 0 { + return fmt.Errorf("NewChainSelector must be set") + } + if len(c.SourceChainSelectors) == 0 { + return fmt.Errorf("SourceChainSelectors must be set") + } + return nil +} + +// NewChainInboundChangeset generates a proposal +// to connect the new chain to the existing chains. +func NewChainInboundChangeset( + e deployment.Environment, + cfg ChainInboundChangesetConfig, +) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(); err != nil { + return deployment.ChangesetOutput{}, err + } + + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + // Generate proposal which enables new destination (from test router) on all source chains. + var batches []timelock.BatchChainOperation + for _, source := range cfg.SourceChainSelectors { + enableOnRampDest, err := state.Chains[source].OnRamp.ApplyDestChainConfigUpdates(deployment.SimTransactOpts(), []onramp.OnRampDestChainConfigArgs{ + { + DestChainSelector: cfg.NewChainSelector, + Router: state.Chains[source].TestRouter.Address(), + }, + }) + if err != nil { + return deployment.ChangesetOutput{}, err + } + enableFeeQuoterDest, err := state.Chains[source].FeeQuoter.ApplyDestChainConfigUpdates( + deployment.SimTransactOpts(), + []fee_quoter.FeeQuoterDestChainConfigArgs{ + { + DestChainSelector: cfg.NewChainSelector, + DestChainConfig: DefaultFeeQuoterDestChainConfig(), + }, + }) + if err != nil { + return deployment.ChangesetOutput{}, err + } + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(source), + Batch: []mcms.Operation{ + { + // Enable the source in on ramp + To: state.Chains[source].OnRamp.Address(), + Data: enableOnRampDest.Data(), + Value: big.NewInt(0), + }, + { + To: state.Chains[source].FeeQuoter.Address(), + Data: enableFeeQuoterDest.Data(), + Value: big.NewInt(0), + }, + }, + }) + } + + addChainOp, err := applyChainConfigUpdatesOp(e, state, cfg.HomeChainSelector, []uint64{cfg.NewChainSelector}) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), + Batch: []mcms.Operation{ + addChainOp, + }, + }) + + var ( + timelocksPerChain = make(map[uint64]common.Address) + proposerMCMSes = make(map[uint64]*gethwrappers.ManyChainMultiSig) + ) + for _, chain := range append(cfg.SourceChainSelectors, cfg.HomeChainSelector) { + timelocksPerChain[chain] = state.Chains[chain].Timelock.Address() + proposerMCMSes[chain] = state.Chains[chain].ProposerMcm + } + prop, err := proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + batches, + "proposal to set new chains", + 0, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{*prop}, + }, nil +} + +type AddDonAndSetCandidateChangesetConfig struct { + HomeChainSelector uint64 + FeedChainSelector uint64 + NewChainSelector uint64 + PluginType types.PluginType + NodeIDs []string + CCIPOCRParams CCIPOCRParams +} + +func (a AddDonAndSetCandidateChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) (deployment.Nodes, error) { + if a.HomeChainSelector == 0 { + return nil, fmt.Errorf("HomeChainSelector must be set") + } + if a.FeedChainSelector == 0 { + return nil, fmt.Errorf("FeedChainSelector must be set") + } + if a.NewChainSelector == 0 { + return nil, fmt.Errorf("ocr config chain selector must be set") + } + if a.PluginType != types.PluginTypeCCIPCommit && + a.PluginType != types.PluginTypeCCIPExec { + return nil, fmt.Errorf("PluginType must be set to either CCIPCommit or CCIPExec") + } + // TODO: validate token config + if len(a.NodeIDs) == 0 { + return nil, fmt.Errorf("nodeIDs must be set") + } + nodes, err := deployment.NodeInfo(a.NodeIDs, e.Offchain) + if err != nil { + return nil, fmt.Errorf("get node info: %w", err) + } + + // check that chain config is set up for the new chain + // TODO: feels like we should just have a getter for a particular chain, this pagination + // logic seems a bit out of place here. + allConfigs, err := state.Chains[a.HomeChainSelector].CCIPHome.GetAllChainConfigs(nil, big.NewInt(0), big.NewInt(100)) + if err != nil { + return nil, fmt.Errorf("get all chain configs: %w", err) + } + var found bool + for _, chainConfig := range allConfigs { + if chainConfig.ChainSelector == a.NewChainSelector { + found = true + break + } + } + if !found { + return nil, fmt.Errorf("chain config not set for chain %d", a.NewChainSelector) + } + + err = a.CCIPOCRParams.Validate() + if err != nil { + return nil, fmt.Errorf("invalid ccip ocr params: %w", err) + } + + if e.OCRSecrets.IsEmpty() { + return nil, fmt.Errorf("OCR secrets must be set") + } + + return nodes, nil +} + +// AddDonAndSetCandidateChangeset adds new DON for destination to home chain +// and sets the commit plugin config as candidateConfig for the don. +func AddDonAndSetCandidateChangeset( + e deployment.Environment, + cfg AddDonAndSetCandidateChangesetConfig, +) (deployment.ChangesetOutput, error) { + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + nodes, err := cfg.Validate(e, state) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) + } + + newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( + e.OCRSecrets, + state.Chains[cfg.NewChainSelector].OffRamp, + e.Chains[cfg.NewChainSelector], + nodes.NonBootstraps(), + state.Chains[cfg.HomeChainSelector].RMNHome.Address(), + cfg.CCIPOCRParams.OCRParameters, + cfg.CCIPOCRParams.CommitOffChainConfig, + cfg.CCIPOCRParams.ExecuteOffChainConfig, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + latestDon, err := internal.LatestCCIPDON(state.Chains[cfg.HomeChainSelector].CapabilityRegistry) + if err != nil { + return deployment.ChangesetOutput{}, err + } + commitConfig, ok := newDONArgs[cfg.PluginType] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("missing commit plugin in ocr3Configs") + } + donID := latestDon.Id + 1 + addDonOp, err := newDonWithCandidateOp( + donID, commitConfig, + state.Chains[cfg.HomeChainSelector].CapabilityRegistry, + nodes.NonBootstraps(), + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + var ( + timelocksPerChain = map[uint64]common.Address{ + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), + } + proposerMCMSes = map[uint64]*gethwrappers.ManyChainMultiSig{ + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, + } + ) + prop, err := proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), + Batch: []mcms.Operation{addDonOp}, + }}, + "setCandidate for commit and AddDon on new Chain", + 0, // minDelay + ) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal from batch: %w", err) + } + + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{*prop}, + }, nil +} + +func applyChainConfigUpdatesOp( + e deployment.Environment, + state CCIPOnChainState, + homeChainSel uint64, + chains []uint64, +) (mcms.Operation, error) { + nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + if err != nil { + return mcms.Operation{}, err + } + encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ + GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), + DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), + OptimisticConfirmations: 1, + }) + if err != nil { + return mcms.Operation{}, err + } + var chainConfigUpdates []ccip_home.CCIPHomeChainConfigArgs + for _, chainSel := range chains { + chainConfig := setupConfigInfo(chainSel, nodes.NonBootstraps().PeerIDs(), + nodes.DefaultF(), encodedExtraChainConfig) + chainConfigUpdates = append(chainConfigUpdates, chainConfig) + } + + addChain, err := state.Chains[homeChainSel].CCIPHome.ApplyChainConfigUpdates( + deployment.SimTransactOpts(), + nil, + chainConfigUpdates, + ) + if err != nil { + return mcms.Operation{}, err + } + return mcms.Operation{ + To: state.Chains[homeChainSel].CCIPHome.Address(), + Data: addChain.Data(), + Value: big.NewInt(0), + }, nil +} + +// newDonWithCandidateOp sets the candidate commit config by calling setCandidate on CCIPHome contract through the AddDON call on CapReg contract +// This should be done first before calling any other UpdateDON calls +// This proposes to set up OCR3 config for the commit plugin for the DON +func newDonWithCandidateOp( + donID uint32, + pluginConfig ccip_home.CCIPHomeOCR3Config, + capReg *capabilities_registry.CapabilitiesRegistry, + nodes deployment.Nodes, +) (mcms.Operation, error) { + encodedSetCandidateCall, err := internal.CCIPHomeABI.Pack( + "setCandidate", + donID, + pluginConfig.PluginType, + pluginConfig, + [32]byte{}, + ) + if err != nil { + return mcms.Operation{}, fmt.Errorf("pack set candidate call: %w", err) + } + addDonTx, err := capReg.AddDON(deployment.SimTransactOpts(), nodes.PeerIDs(), []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: internal.CCIPCapabilityID, + Config: encodedSetCandidateCall, + }, + }, false, false, nodes.DefaultF()) + if err != nil { + return mcms.Operation{}, fmt.Errorf("could not generate add don tx w/ commit config: %w", err) + } + return mcms.Operation{ + To: capReg.Address(), + Data: addDonTx.Data(), + Value: big.NewInt(0), + }, nil +} diff --git a/deployment/ccip/changeset/add_chain_test.go b/deployment/ccip/changeset/cs_add_chain_test.go similarity index 64% rename from deployment/ccip/changeset/add_chain_test.go rename to deployment/ccip/changeset/cs_add_chain_test.go index db19cd5fa41..c8d872236c2 100644 --- a/deployment/ccip/changeset/add_chain_test.go +++ b/deployment/ccip/changeset/cs_add_chain_test.go @@ -5,9 +5,12 @@ import ( "testing" "time" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/ethereum/go-ethereum/common" @@ -31,7 +34,12 @@ import ( func TestAddChainInbound(t *testing.T) { // 4 chains where the 4th is added after initial deployment. - e := NewMemoryEnvironmentWithJobs(t, logger.TestLogger(t), 4, 4) + e := NewMemoryEnvironmentWithJobs(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 4, + NumOfUsersPerChain: 1, + Nodes: 4, + Bootstraps: 1, + }) state, err := LoadOnchainState(e.Env) require.NoError(t, err) // Take first non-home chain as the new chain. @@ -50,22 +58,32 @@ func TestAddChainInbound(t *testing.T) { TimelockExecutors: e.Env.AllDeployerKeys(), TimelockMinDelay: big.NewInt(0), } - out, err := commonchangeset.DeployMCMSWithTimelock(e.Env, map[uint64]commontypes.MCMSWithTimelockConfig{ - initialDeploy[0]: cfg, - initialDeploy[1]: cfg, - initialDeploy[2]: cfg, + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: initialDeploy, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: map[uint64]commontypes.MCMSWithTimelockConfig{ + initialDeploy[0]: cfg, + initialDeploy[1]: cfg, + initialDeploy[2]: cfg, + }, + }, }) require.NoError(t, err) - require.NoError(t, e.Env.ExistingAddresses.Merge(out.AddressBook)) newAddresses = deployment.NewMemoryAddressBook() tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) + chainConfig := make(map[uint64]CCIPOCRParams) + for _, chain := range initialDeploy { + chainConfig[chain] = DefaultOCRParams(e.FeedChainSel, nil, nil) + } err = deployCCIPContracts(e.Env, newAddresses, NewChainsConfig{ - HomeChainSel: e.HomeChainSel, - FeedChainSel: e.FeedChainSel, - ChainsToDeploy: initialDeploy, - TokenConfig: tokenConfig, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + HomeChainSel: e.HomeChainSel, + FeedChainSel: e.FeedChainSel, + ChainConfigByChain: chainConfig, }) require.NoError(t, err) @@ -88,12 +106,19 @@ func TestAddChainInbound(t *testing.T) { require.NoError(t, err) // Deploy contracts to new chain - out, err = commonchangeset.DeployMCMSWithTimelock(e.Env, map[uint64]commontypes.MCMSWithTimelockConfig{ - newChain: cfg, + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: []uint64{newChain}, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: map[uint64]commontypes.MCMSWithTimelockConfig{ + newChain: cfg, + }, + }, }) require.NoError(t, err) - require.NoError(t, e.Env.ExistingAddresses.Merge(out.AddressBook)) - newAddresses = deployment.NewMemoryAddressBook() err = deployPrerequisiteChainContracts(e.Env, newAddresses, []uint64{newChain}, nil) @@ -107,18 +132,9 @@ func TestAddChainInbound(t *testing.T) { state, err = LoadOnchainState(e.Env) require.NoError(t, err) - // Transfer onramp/fq ownership to timelock. - // Enable the new dest on the test router. + // configure the testrouter appropriately on each chain for _, source := range initialDeploy { - tx, err := state.Chains[source].OnRamp.TransferOwnership(e.Env.Chains[source].DeployerKey, state.Chains[source].Timelock.Address()) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(e.Env.Chains[source], tx, err) - require.NoError(t, err) - tx, err = state.Chains[source].FeeQuoter.TransferOwnership(e.Env.Chains[source].DeployerKey, state.Chains[source].Timelock.Address()) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(e.Env.Chains[source], tx, err) - require.NoError(t, err) - tx, err = state.Chains[source].TestRouter.ApplyRampUpdates(e.Env.Chains[source].DeployerKey, []router.RouterOnRamp{ + tx, err := state.Chains[source].TestRouter.ApplyRampUpdates(e.Env.Chains[source].DeployerKey, []router.RouterOnRamp{ { DestChainSelector: newChain, OnRamp: state.Chains[source].OnRamp.Address(), @@ -127,64 +143,88 @@ func TestAddChainInbound(t *testing.T) { _, err = deployment.ConfirmIfNoError(e.Env.Chains[source], tx, err) require.NoError(t, err) } - // Transfer CR contract ownership - tx, err := state.Chains[e.HomeChainSel].CapabilityRegistry.TransferOwnership(e.Env.Chains[e.HomeChainSel].DeployerKey, state.Chains[e.HomeChainSel].Timelock.Address()) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(e.Env.Chains[e.HomeChainSel], tx, err) - require.NoError(t, err) - tx, err = state.Chains[e.HomeChainSel].CCIPHome.TransferOwnership(e.Env.Chains[e.HomeChainSel].DeployerKey, state.Chains[e.HomeChainSel].Timelock.Address()) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(e.Env.Chains[e.HomeChainSel], tx, err) - require.NoError(t, err) - acceptOwnershipProposal, err := GenerateAcceptOwnershipProposal(state, e.HomeChainSel, initialDeploy) - require.NoError(t, err) - acceptOwnershipExec := commonchangeset.SignProposal(t, e.Env, acceptOwnershipProposal) - // Apply the accept ownership proposal to all the chains. - for _, sel := range initialDeploy { - commonchangeset.ExecuteProposal(t, e.Env, acceptOwnershipExec, state.Chains[sel].Timelock, sel) - } - for _, chain := range initialDeploy { - owner, err2 := state.Chains[chain].OnRamp.Owner(nil) - require.NoError(t, err2) - require.Equal(t, state.Chains[chain].Timelock.Address(), owner) - } - cfgOwner, err := state.Chains[e.HomeChainSel].CCIPHome.Owner(nil) - require.NoError(t, err) - crOwner, err := state.Chains[e.HomeChainSel].CapabilityRegistry.Owner(nil) + // transfer ownership to timelock + _, err = commonchangeset.ApplyChangesets(t, e.Env, map[uint64]*gethwrappers.RBACTimelock{ + initialDeploy[0]: state.Chains[initialDeploy[0]].Timelock, + initialDeploy[1]: state.Chains[initialDeploy[1]].Timelock, + initialDeploy[2]: state.Chains[initialDeploy[2]].Timelock, + }, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), + Config: genTestTransferOwnershipConfig(e, initialDeploy, state), + }, + { + Changeset: commonchangeset.WrapChangeSet(NewChainInboundChangeset), + Config: ChainInboundChangesetConfig{ + HomeChainSelector: e.HomeChainSel, + NewChainSelector: newChain, + SourceChainSelectors: initialDeploy, + }, + }, + }) require.NoError(t, err) - require.Equal(t, state.Chains[e.HomeChainSel].Timelock.Address(), cfgOwner) - require.Equal(t, state.Chains[e.HomeChainSel].Timelock.Address(), crOwner) - nodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) - require.NoError(t, err) + assertTimelockOwnership(t, e, initialDeploy, state) - // Generate and sign inbound proposal to new 4th chain. - chainInboundChangeset, err := NewChainInboundChangeset(e.Env, state, e.HomeChainSel, newChain, initialDeploy) + nodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) require.NoError(t, err) - ProcessChangeset(t, e.Env, chainInboundChangeset) // TODO This currently is not working - Able to send the request here but request gets stuck in execution // Send a new message and expect that this is delivered once the chain is completely set up as inbound //TestSendRequest(t, e.Env, state, initialDeploy[0], newChain, true) + var nodeIDs []string + for _, node := range nodes { + nodeIDs = append(nodeIDs, node.NodeID) + } - t.Logf("Executing add don and set candidate proposal for commit plugin on chain %d", newChain) - addDonChangeset, err := AddDonAndSetCandidateChangeset(state, e.Env, nodes, deployment.XXXGenerateTestOCRSecrets(), e.HomeChainSel, e.FeedChainSel, newChain, tokenConfig, types.PluginTypeCCIPCommit) - require.NoError(t, err) - ProcessChangeset(t, e.Env, addDonChangeset) - - t.Logf("Executing promote candidate proposal for exec plugin on chain %d", newChain) - setCandidateForExecChangeset, err := SetCandidatePluginChangeset(state, e.Env, nodes, deployment.XXXGenerateTestOCRSecrets(), e.HomeChainSel, e.FeedChainSel, newChain, tokenConfig, types.PluginTypeCCIPExec) - require.NoError(t, err) - ProcessChangeset(t, e.Env, setCandidateForExecChangeset) - - t.Logf("Executing promote candidate proposal for both commit and exec plugins on chain %d", newChain) - donPromoteChangeset, err := PromoteAllCandidatesChangeset(state, e.HomeChainSel, newChain, nodes) - require.NoError(t, err) - ProcessChangeset(t, e.Env, donPromoteChangeset) + _, err = commonchangeset.ApplyChangesets(t, e.Env, map[uint64]*gethwrappers.RBACTimelock{ + e.HomeChainSel: state.Chains[e.HomeChainSel].Timelock, + newChain: state.Chains[newChain].Timelock, + }, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(AddDonAndSetCandidateChangeset), + Config: AddDonAndSetCandidateChangesetConfig{ + HomeChainSelector: e.HomeChainSel, + FeedChainSelector: e.FeedChainSel, + NewChainSelector: newChain, + PluginType: types.PluginTypeCCIPCommit, + NodeIDs: nodeIDs, + CCIPOCRParams: DefaultOCRParams( + e.FeedChainSel, + tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[newChain].LinkToken, state.Chains[newChain].Weth9), + nil, + ), + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(SetCandidatePluginChangeset), + Config: AddDonAndSetCandidateChangesetConfig{ + HomeChainSelector: e.HomeChainSel, + FeedChainSelector: e.FeedChainSel, + NewChainSelector: newChain, + PluginType: types.PluginTypeCCIPExec, + NodeIDs: nodeIDs, + CCIPOCRParams: DefaultOCRParams( + e.FeedChainSel, + tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[newChain].LinkToken, state.Chains[newChain].Weth9), + nil, + ), + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(PromoteAllCandidatesChangeset), + Config: PromoteAllCandidatesChangesetConfig{ + HomeChainSelector: e.HomeChainSel, + NewChainSelector: newChain, + NodeIDs: nodeIDs, + }, + }, + }) // verify if the configs are updated require.NoError(t, ValidateCCIPHomeConfigSetUp( + e.Env.Logger, state.Chains[e.HomeChainSel].CapabilityRegistry, state.Chains[e.HomeChainSel].CCIPHome, newChain, @@ -202,7 +242,7 @@ func TestAddChainInbound(t *testing.T) { OnRamp: common.LeftPadBytes(state.Chains[source].OnRamp.Address().Bytes(), 32), }) } - tx, err = state.Chains[newChain].OffRamp.ApplySourceChainConfigUpdates(e.Env.Chains[newChain].DeployerKey, offRampEnables) + tx, err := state.Chains[newChain].OffRamp.ApplySourceChainConfigUpdates(e.Env.Chains[newChain].DeployerKey, offRampEnables) require.NoError(t, err) _, err = deployment.ConfirmIfNoError(e.Env.Chains[newChain], tx, err) require.NoError(t, err) @@ -250,7 +290,7 @@ func TestAddChainInbound(t *testing.T) { commonutils.JustError(ConfirmCommitWithExpectedSeqNumRange(t, e.Env.Chains[initialDeploy[0]], e.Env.Chains[newChain], state.Chains[newChain].OffRamp, &startBlock, cciptypes.SeqNumRange{ cciptypes.SeqNum(1), cciptypes.SeqNum(msgSentEvent.SequenceNumber), - }))) + }, true))) require.NoError(t, commonutils.JustError( ConfirmExecWithSeqNrs( diff --git a/deployment/ccip/changeset/add_lane.go b/deployment/ccip/changeset/cs_add_lane.go similarity index 87% rename from deployment/ccip/changeset/add_lane.go rename to deployment/ccip/changeset/cs_add_lane.go index 0b16611021f..0bd03b56559 100644 --- a/deployment/ccip/changeset/add_lane.go +++ b/deployment/ccip/changeset/cs_add_lane.go @@ -10,14 +10,13 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" ) -var _ deployment.ChangeSet[AddLanesConfig] = AddLanesWithTestRouter +var _ deployment.ChangeSet[AddLanesConfig] = AddLanes type InitialPrices struct { LinkPrice *big.Int // USD to the power of 18 (e18) per LINK @@ -43,6 +42,7 @@ type LaneConfig struct { DestSelector uint64 InitialPricesBySource InitialPrices FeeQuoterDestChain fee_quoter.FeeQuoterDestChainConfig + TestRouter bool } type AddLanesConfig struct { @@ -65,12 +65,12 @@ func (c AddLanesConfig) Validate() error { return nil } -// AddLanesWithTestRouter adds lanes between chains using the test router. -// AddLanesWithTestRouter is run while the contracts are still owned by the deployer. +// AddLanes adds lanes between chains. +// AddLanes is run while the contracts are still owned by the deployer. // This is useful to test the initial deployment to enable lanes between chains. -// Once the testrouter is enabled, the lanes can be used to send messages between chains with testrouter. -// On successful verification with testrouter, the lanes can be enabled with the main router with different AddLane ChangeSet. -func AddLanesWithTestRouter(e deployment.Environment, cfg AddLanesConfig) (deployment.ChangesetOutput, error) { +// If the testrouter is enabled, the lanes can be used to send messages between chains with testrouter. +// On successful verification with testrouter, the lanes can be enabled with the main router with different addLane ChangeSet. +func AddLanes(e deployment.Environment, cfg AddLanesConfig) (deployment.ChangesetOutput, error) { if err := cfg.Validate(); err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("invalid AddLanesConfig: %w", err) } @@ -100,24 +100,14 @@ func addLanes(e deployment.Environment, cfg AddLanesConfig) error { } for _, laneCfg := range cfg.LaneConfigs { e.Logger.Infow("Enabling lane with test router", "from", laneCfg.SourceSelector, "to", laneCfg.DestSelector) - if err := AddLane(e, state, laneCfg, true); err != nil { + if err := addLane(e, state, laneCfg, laneCfg.TestRouter); err != nil { return err } } return nil } -func AddLaneWithDefaultPricesAndFeeQuoterConfig(e deployment.Environment, state CCIPOnChainState, from, to uint64, isTestRouter bool) error { - cfg := LaneConfig{ - SourceSelector: from, - DestSelector: to, - InitialPricesBySource: DefaultInitialPrices, - FeeQuoterDestChain: DefaultFeeQuoterDestChainConfig(), - } - return AddLane(e, state, cfg, isTestRouter) -} - -func AddLane(e deployment.Environment, state CCIPOnChainState, config LaneConfig, isTestRouter bool) error { +func addLane(e deployment.Environment, state CCIPOnChainState, config LaneConfig, isTestRouter bool) error { // TODO: Batch var fromRouter *router.Router var toRouter *router.Router diff --git a/deployment/ccip/changeset/add_lane_test.go b/deployment/ccip/changeset/cs_add_lane_test.go similarity index 95% rename from deployment/ccip/changeset/add_lane_test.go rename to deployment/ccip/changeset/cs_add_lane_test.go index dff17d8010a..fbceeaa8472 100644 --- a/deployment/ccip/changeset/add_lane_test.go +++ b/deployment/ccip/changeset/cs_add_lane_test.go @@ -11,13 +11,18 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/logger" ) func TestAddLanesWithTestRouter(t *testing.T) { - e := NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), 2, 4, nil) + e := NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + }, nil) // Here we have CR + nodes set up, but no CCIP contracts deployed. state, err := LoadOnchainState(e.Env) require.NoError(t, err) @@ -25,13 +30,14 @@ func TestAddLanesWithTestRouter(t *testing.T) { selectors := e.Env.AllChainSelectors() chain1, chain2 := selectors[0], selectors[1] - _, err = AddLanesWithTestRouter(e.Env, AddLanesConfig{ + _, err = AddLanes(e.Env, AddLanesConfig{ LaneConfigs: []LaneConfig{ { SourceSelector: chain1, DestSelector: chain2, InitialPricesBySource: DefaultInitialPrices, FeeQuoterDestChain: DefaultFeeQuoterDestChainConfig(), + TestRouter: true, }, }, }) @@ -66,7 +72,11 @@ func TestAddLane(t *testing.T) { t.Parallel() // We add more chains to the chainlink nodes than the number of chains where CCIP is deployed. - e := NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), 2, 4, nil) + e := NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + }, nil) // Here we have CR + nodes set up, but no CCIP contracts deployed. state, err := LoadOnchainState(e.Env) require.NoError(t, err) diff --git a/deployment/ccip/changeset/cs_deploy_chain.go b/deployment/ccip/changeset/cs_deploy_chain.go new file mode 100644 index 00000000000..e2762b27578 --- /dev/null +++ b/deployment/ccip/changeset/cs_deploy_chain.go @@ -0,0 +1,459 @@ +package changeset + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "golang.org/x/sync/errgroup" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" +) + +var _ deployment.ChangeSet[DeployChainContractsConfig] = DeployChainContracts + +// DeployChainContracts deploys all new CCIP v1.6 or later contracts for the given chains. +// It returns the new addresses for the contracts. +// DeployChainContracts is idempotent. If there is an error, it will return the successfully deployed addresses and the error so that the caller can call the +// changeset again with the same input to retry the failed deployment. +// Caller should update the environment's address book with the returned addresses. +func DeployChainContracts(env deployment.Environment, c DeployChainContractsConfig) (deployment.ChangesetOutput, error) { + if err := c.Validate(); err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("invalid DeployChainContractsConfig: %w", err) + } + newAddresses := deployment.NewMemoryAddressBook() + err := deployChainContractsForChains(env, newAddresses, c.HomeChainSelector, c.ChainSelectors) + if err != nil { + env.Logger.Errorw("Failed to deploy CCIP contracts", "err", err, "newAddresses", newAddresses) + return deployment.ChangesetOutput{AddressBook: newAddresses}, deployment.MaybeDataErr(err) + } + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{}, + AddressBook: newAddresses, + JobSpecs: nil, + }, nil +} + +type DeployChainContractsConfig struct { + ChainSelectors []uint64 + HomeChainSelector uint64 +} + +func (c DeployChainContractsConfig) Validate() error { + for _, cs := range c.ChainSelectors { + if err := deployment.IsValidChainSelector(cs); err != nil { + return fmt.Errorf("invalid chain selector: %d - %w", cs, err) + } + } + if err := deployment.IsValidChainSelector(c.HomeChainSelector); err != nil { + return fmt.Errorf("invalid home chain selector: %d - %w", c.HomeChainSelector, err) + } + return nil +} + +// deployCCIPContracts assumes the following contracts are deployed: +// - Capability registry +// - CCIP home +// - RMN home +// - Fee tokens on all chains. +// and present in ExistingAddressBook. +// It then deploys the rest of the CCIP chain contracts to the selected chains +// registers the nodes with the capability registry and creates a DON for +// each new chain. +func deployCCIPContracts( + e deployment.Environment, + ab deployment.AddressBook, + c NewChainsConfig) error { + err := deployChainContractsForChains(e, ab, c.HomeChainSel, c.Chains()) + if err != nil { + e.Logger.Errorw("Failed to deploy chain contracts", "err", err) + return err + } + err = e.ExistingAddresses.Merge(ab) + if err != nil { + e.Logger.Errorw("Failed to merge address book", "err", err) + return err + } + err = configureChain(e, c) + if err != nil { + e.Logger.Errorw("Failed to add chain", "err", err) + return err + } + + return nil +} + +func deployChainContractsForChains( + e deployment.Environment, + ab deployment.AddressBook, + homeChainSel uint64, + chainsToDeploy []uint64) error { + existingState, err := LoadOnchainState(e) + if err != nil { + e.Logger.Errorw("Failed to load existing onchain state", "err") + return err + } + + capReg := existingState.Chains[homeChainSel].CapabilityRegistry + if capReg == nil { + e.Logger.Errorw("Failed to get capability registry") + return fmt.Errorf("capability registry not found") + } + cr, err := capReg.GetHashedCapabilityId( + &bind.CallOpts{}, internal.CapabilityLabelledName, internal.CapabilityVersion) + if err != nil { + e.Logger.Errorw("Failed to get hashed capability id", "err", err) + return err + } + if cr != internal.CCIPCapabilityID { + return fmt.Errorf("unexpected mismatch between calculated ccip capability id (%s) and expected ccip capability id constant (%s)", + hexutil.Encode(cr[:]), + hexutil.Encode(internal.CCIPCapabilityID[:])) + } + capability, err := capReg.GetCapability(nil, internal.CCIPCapabilityID) + if err != nil { + e.Logger.Errorw("Failed to get capability", "err", err) + return err + } + ccipHome, err := ccip_home.NewCCIPHome(capability.ConfigurationContract, e.Chains[homeChainSel].Client) + if err != nil { + e.Logger.Errorw("Failed to get ccip config", "err", err) + return err + } + if ccipHome.Address() != existingState.Chains[homeChainSel].CCIPHome.Address() { + return fmt.Errorf("ccip home address mismatch") + } + rmnHome := existingState.Chains[homeChainSel].RMNHome + if rmnHome == nil { + e.Logger.Errorw("Failed to get rmn home", "err", err) + return fmt.Errorf("rmn home not found") + } + deployGrp := errgroup.Group{} + for _, chainSel := range chainsToDeploy { + chain, ok := e.Chains[chainSel] + if !ok { + return fmt.Errorf("chain %d not found", chainSel) + } + if existingState.Chains[chainSel].LinkToken == nil || existingState.Chains[chainSel].Weth9 == nil { + return fmt.Errorf("fee tokens not found for chain %d", chainSel) + } + deployGrp.Go( + func() error { + err := deployChainContracts(e, chain, ab, rmnHome) + if err != nil { + e.Logger.Errorw("Failed to deploy chain contracts", "chain", chainSel, "err", err) + return fmt.Errorf("failed to deploy chain contracts for chain %d: %w", chainSel, err) + } + return nil + }) + } + if err := deployGrp.Wait(); err != nil { + e.Logger.Errorw("Failed to deploy chain contracts", "err", err) + return err + } + return nil +} + +func deployChainContracts( + e deployment.Environment, + chain deployment.Chain, + ab deployment.AddressBook, + rmnHome *rmn_home.RMNHome, +) error { + // check for existing contracts + state, err := LoadOnchainState(e) + if err != nil { + e.Logger.Errorw("Failed to load existing onchain state", "err") + return err + } + chainState, chainExists := state.Chains[chain.Selector] + if !chainExists { + return fmt.Errorf("chain %s not found in existing state, deploy the prerequisites first", chain.String()) + } + if chainState.Weth9 == nil { + return fmt.Errorf("weth9 not found for chain %s, deploy the prerequisites first", chain.String()) + } + if chainState.Timelock == nil { + return fmt.Errorf("timelock not found for chain %s, deploy the mcms contracts first", chain.String()) + } + weth9Contract := chainState.Weth9 + if chainState.LinkToken == nil { + return fmt.Errorf("link token not found for chain %s, deploy the prerequisites first", chain.String()) + } + linkTokenContract := chainState.LinkToken + if chainState.TokenAdminRegistry == nil { + return fmt.Errorf("token admin registry not found for chain %s, deploy the prerequisites first", chain.String()) + } + tokenAdminReg := chainState.TokenAdminRegistry + if chainState.RegistryModule == nil { + return fmt.Errorf("registry module not found for chain %s, deploy the prerequisites first", chain.String()) + } + if chainState.Router == nil { + return fmt.Errorf("router not found for chain %s, deploy the prerequisites first", chain.String()) + } + if chainState.Receiver == nil { + _, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver] { + receiverAddr, tx, receiver, err2 := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver( + chain.DeployerKey, + chain.Client, + false, + ) + return deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver]{ + receiverAddr, receiver, tx, deployment.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy receiver", "err", err) + return err + } + } else { + e.Logger.Infow("receiver already deployed", "addr", chainState.Receiver.Address, "chain", chain.String()) + } + rmnRemoteContract := chainState.RMNRemote + if chainState.RMNRemote == nil { + // TODO: Correctly configure RMN remote. + rmnRemote, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*rmn_remote.RMNRemote] { + rmnRemoteAddr, tx, rmnRemote, err2 := rmn_remote.DeployRMNRemote( + chain.DeployerKey, + chain.Client, + chain.Selector, + // Indicates no legacy RMN contract + common.HexToAddress("0x0"), + ) + return deployment.ContractDeploy[*rmn_remote.RMNRemote]{ + rmnRemoteAddr, rmnRemote, tx, deployment.NewTypeAndVersion(RMNRemote, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy RMNRemote", "chain", chain.String(), "err", err) + return err + } + rmnRemoteContract = rmnRemote.Contract + } else { + e.Logger.Infow("rmn remote already deployed", "chain", chain.String(), "addr", chainState.RMNRemote.Address) + } + activeDigest, err := rmnHome.GetActiveDigest(&bind.CallOpts{}) + if err != nil { + e.Logger.Errorw("Failed to get active digest", "chain", chain.String(), "err", err) + return err + } + e.Logger.Infow("setting active home digest to rmn remote", "chain", chain.String(), "digest", activeDigest) + + tx, err := rmnRemoteContract.SetConfig(chain.DeployerKey, rmn_remote.RMNRemoteConfig{ + RmnHomeContractConfigDigest: activeDigest, + Signers: []rmn_remote.RMNRemoteSigner{ + {NodeIndex: 0, OnchainPublicKey: common.Address{1}}, + }, + F: 0, // TODO: update when we have signers + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + e.Logger.Errorw("Failed to confirm RMNRemote config", "chain", chain.String(), "err", err) + return err + } + + // we deploy a new RMNProxy so that RMNRemote can be tested first before pointing it to the main Existing RMNProxy + // To differentiate between the two RMNProxies, we will deploy new one with Version1_6_0_dev + rmnProxyContract := chainState.RMNProxyNew + if chainState.RMNProxyNew == nil { + // we deploy a new rmnproxy contract to test RMNRemote + rmnProxy, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract] { + rmnProxyAddr, tx, rmnProxy, err2 := rmn_proxy_contract.DeployRMNProxyContract( + chain.DeployerKey, + chain.Client, + rmnRemoteContract.Address(), + ) + return deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract]{ + rmnProxyAddr, rmnProxy, tx, deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy RMNProxyNew", "chain", chain.String(), "err", err) + return err + } + rmnProxyContract = rmnProxy.Contract + } else { + e.Logger.Infow("rmn proxy already deployed", "chain", chain.String(), "addr", chainState.RMNProxyNew.Address) + } + if chainState.TestRouter == nil { + _, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*router.Router] { + routerAddr, tx2, routerC, err2 := router.DeployRouter( + chain.DeployerKey, + chain.Client, + weth9Contract.Address(), + rmnProxyContract.Address(), + ) + return deployment.ContractDeploy[*router.Router]{ + routerAddr, routerC, tx2, deployment.NewTypeAndVersion(TestRouter, deployment.Version1_2_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy test router", "chain", chain.String(), "err", err) + return err + } + } else { + e.Logger.Infow("test router already deployed", "chain", chain.String(), "addr", chainState.TestRouter.Address) + } + + nmContract := chainState.NonceManager + if chainState.NonceManager == nil { + nonceManager, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*nonce_manager.NonceManager] { + nonceManagerAddr, tx2, nonceManager, err2 := nonce_manager.DeployNonceManager( + chain.DeployerKey, + chain.Client, + []common.Address{}, // Need to add onRamp after + ) + return deployment.ContractDeploy[*nonce_manager.NonceManager]{ + nonceManagerAddr, nonceManager, tx2, deployment.NewTypeAndVersion(NonceManager, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy nonce manager", "chain", chain.String(), "err", err) + return err + } + nmContract = nonceManager.Contract + } else { + e.Logger.Infow("nonce manager already deployed", "chain", chain.String(), "addr", chainState.NonceManager.Address) + } + feeQuoterContract := chainState.FeeQuoter + if chainState.FeeQuoter == nil { + feeQuoter, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*fee_quoter.FeeQuoter] { + prAddr, tx2, pr, err2 := fee_quoter.DeployFeeQuoter( + chain.DeployerKey, + chain.Client, + fee_quoter.FeeQuoterStaticConfig{ + MaxFeeJuelsPerMsg: big.NewInt(0).Mul(big.NewInt(2e2), big.NewInt(1e18)), + LinkToken: linkTokenContract.Address(), + TokenPriceStalenessThreshold: uint32(24 * 60 * 60), + }, + []common.Address{state.Chains[chain.Selector].Timelock.Address()}, // timelock should be able to update, ramps added after + []common.Address{weth9Contract.Address(), linkTokenContract.Address()}, // fee tokens + []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, + []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, // TODO: tokens + []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{ + { + PremiumMultiplierWeiPerEth: 9e17, // 0.9 ETH + Token: linkTokenContract.Address(), + }, + { + PremiumMultiplierWeiPerEth: 1e18, + Token: weth9Contract.Address(), + }, + }, + []fee_quoter.FeeQuoterDestChainConfigArgs{}, + ) + return deployment.ContractDeploy[*fee_quoter.FeeQuoter]{ + prAddr, pr, tx2, deployment.NewTypeAndVersion(FeeQuoter, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy fee quoter", "chain", chain.String(), "err", err) + return err + } + feeQuoterContract = feeQuoter.Contract + } else { + e.Logger.Infow("fee quoter already deployed", "chain", chain.String(), "addr", chainState.FeeQuoter.Address) + } + onRampContract := chainState.OnRamp + if onRampContract == nil { + onRamp, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*onramp.OnRamp] { + onRampAddr, tx2, onRamp, err2 := onramp.DeployOnRamp( + chain.DeployerKey, + chain.Client, + onramp.OnRampStaticConfig{ + ChainSelector: chain.Selector, + RmnRemote: rmnProxyContract.Address(), + NonceManager: nmContract.Address(), + TokenAdminRegistry: tokenAdminReg.Address(), + }, + onramp.OnRampDynamicConfig{ + FeeQuoter: feeQuoterContract.Address(), + FeeAggregator: common.HexToAddress("0x1"), // TODO real fee aggregator + }, + []onramp.OnRampDestChainConfigArgs{}, + ) + return deployment.ContractDeploy[*onramp.OnRamp]{ + onRampAddr, onRamp, tx2, deployment.NewTypeAndVersion(OnRamp, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy onramp", "chain", chain.String(), "err", err) + return err + } + onRampContract = onRamp.Contract + } else { + e.Logger.Infow("onramp already deployed", "chain", chain.String(), "addr", chainState.OnRamp.Address) + } + offRampContract := chainState.OffRamp + if offRampContract == nil { + offRamp, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*offramp.OffRamp] { + offRampAddr, tx2, offRamp, err2 := offramp.DeployOffRamp( + chain.DeployerKey, + chain.Client, + offramp.OffRampStaticConfig{ + ChainSelector: chain.Selector, + RmnRemote: rmnProxyContract.Address(), + NonceManager: nmContract.Address(), + TokenAdminRegistry: tokenAdminReg.Address(), + }, + offramp.OffRampDynamicConfig{ + FeeQuoter: feeQuoterContract.Address(), + PermissionLessExecutionThresholdSeconds: uint32(86400), + IsRMNVerificationDisabled: true, + }, + []offramp.OffRampSourceChainConfigArgs{}, + ) + return deployment.ContractDeploy[*offramp.OffRamp]{ + Address: offRampAddr, Contract: offRamp, Tx: tx2, Tv: deployment.NewTypeAndVersion(OffRamp, deployment.Version1_6_0_dev), Err: err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy offramp", "chain", chain.String(), "err", err) + return err + } + offRampContract = offRamp.Contract + } else { + e.Logger.Infow("offramp already deployed", "chain", chain.String(), "addr", chainState.OffRamp.Address) + } + // Basic wiring is always needed. + tx, err = feeQuoterContract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, fee_quoter.AuthorizedCallersAuthorizedCallerArgs{ + // TODO: We enable the deployer initially to set prices + // Should be removed after. + AddedCallers: []common.Address{offRampContract.Address(), chain.DeployerKey.From}, + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + e.Logger.Errorw("Failed to confirm fee quoter authorized caller update", "chain", chain.String(), "err", err) + return err + } + e.Logger.Infow("Added fee quoter authorized callers", "chain", chain.String(), "callers", []common.Address{offRampContract.Address(), chain.DeployerKey.From}) + tx, err = nmContract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, nonce_manager.AuthorizedCallersAuthorizedCallerArgs{ + AddedCallers: []common.Address{offRampContract.Address(), onRampContract.Address()}, + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + e.Logger.Errorw("Failed to update nonce manager with ramps", "chain", chain.String(), "err", err) + return err + } + e.Logger.Infow("Added nonce manager authorized callers", "chain", chain.String(), "callers", []common.Address{offRampContract.Address(), onRampContract.Address()}) + return nil +} diff --git a/deployment/ccip/changeset/deploy_chain_test.go b/deployment/ccip/changeset/cs_deploy_chain_test.go similarity index 58% rename from deployment/ccip/changeset/deploy_chain_test.go rename to deployment/ccip/changeset/cs_deploy_chain_test.go index acab6fde6cb..234d73cc4b5 100644 --- a/deployment/ccip/changeset/deploy_chain_test.go +++ b/deployment/ccip/changeset/cs_deploy_chain_test.go @@ -1,6 +1,8 @@ package changeset import ( + "encoding/json" + "fmt" "math/big" "testing" @@ -26,27 +28,6 @@ func TestDeployChainContractsChangeset(t *testing.T) { nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) require.NoError(t, err) p2pIds := nodes.NonBootstraps().PeerIDs() - // deploy home chain - homeChainCfg := DeployHomeChainConfig{ - HomeChainSel: homeChainSel, - RMNStaticConfig: NewTestRMNStaticConfig(), - RMNDynamicConfig: NewTestRMNDynamicConfig(), - NodeOperators: NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), - NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ - "NodeOperator": p2pIds, - }, - } - output, err := DeployHomeChain(e, homeChainCfg) - require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) - - // deploy pre-requisites - prerequisites, err := DeployPrerequisites(e, DeployPrerequisiteConfig{ - ChainSelectors: selectors, - }) - require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(prerequisites.AddressBook)) - cfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) for _, chain := range e.AllChainSelectors() { cfg[chain] = commontypes.MCMSWithTimelockConfig{ @@ -57,17 +38,42 @@ func TestDeployChainContractsChangeset(t *testing.T) { TimelockMinDelay: big.NewInt(0), } } - output, err = commonchangeset.DeployMCMSWithTimelock(e, cfg) - require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) - - // deploy ccip chain contracts - output, err = DeployChainContracts(e, DeployChainContractsConfig{ - ChainSelectors: selectors, - HomeChainSelector: homeChainSel, + e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(DeployHomeChain), + Config: DeployHomeChainConfig{ + HomeChainSel: homeChainSel, + RMNStaticConfig: NewTestRMNStaticConfig(), + RMNDynamicConfig: NewTestRMNDynamicConfig(), + NodeOperators: NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), + NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ + "NodeOperator": p2pIds, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: selectors, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: cfg, + }, + { + Changeset: commonchangeset.WrapChangeSet(DeployPrerequisites), + Config: DeployPrerequisiteConfig{ + ChainSelectors: selectors, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(DeployChainContracts), + Config: DeployChainContractsConfig{ + ChainSelectors: selectors, + HomeChainSelector: homeChainSel, + }, + }, }) require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) // load onchain state state, err := LoadOnchainState(e) @@ -91,3 +97,23 @@ func TestDeployChainContractsChangeset(t *testing.T) { require.NotNil(t, state.Chains[sel].OnRamp) } } + +func TestDeployCCIPContracts(t *testing.T) { + lggr := logger.TestLogger(t) + e := NewMemoryEnvironmentWithJobsAndContracts(t, lggr, memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + }, nil) + // Deploy all the CCIP contracts. + state, err := LoadOnchainState(e.Env) + require.NoError(t, err) + snap, err := state.View(e.Env.AllChainSelectors()) + require.NoError(t, err) + + // Assert expect every deployed address to be in the address book. + // TODO (CCIP-3047): Add the rest of CCIPv2 representation + b, err := json.MarshalIndent(snap, "", " ") + require.NoError(t, err) + fmt.Println(string(b)) +} diff --git a/deployment/ccip/changeset/cs_home_chain.go b/deployment/ccip/changeset/cs_home_chain.go new file mode 100644 index 00000000000..750b21229aa --- /dev/null +++ b/deployment/ccip/changeset/cs_home_chain.go @@ -0,0 +1,324 @@ +package changeset + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" +) + +var _ deployment.ChangeSet[DeployHomeChainConfig] = DeployHomeChain + +// DeployHomeChain is a separate changeset because it is a standalone deployment performed once in home chain for the entire CCIP deployment. +func DeployHomeChain(env deployment.Environment, cfg DeployHomeChainConfig) (deployment.ChangesetOutput, error) { + err := cfg.Validate() + if err != nil { + return deployment.ChangesetOutput{}, errors.Wrapf(deployment.ErrInvalidConfig, "%v", err) + } + ab := deployment.NewMemoryAddressBook() + // Note we also deploy the cap reg. + _, err = deployHomeChain(env.Logger, env, ab, env.Chains[cfg.HomeChainSel], cfg.RMNStaticConfig, cfg.RMNDynamicConfig, cfg.NodeOperators, cfg.NodeP2PIDsPerNodeOpAdmin) + if err != nil { + env.Logger.Errorw("Failed to deploy cap reg", "err", err, "addresses", env.ExistingAddresses) + return deployment.ChangesetOutput{ + AddressBook: ab, + }, err + } + + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{}, + AddressBook: ab, + JobSpecs: nil, + }, nil +} + +type DeployHomeChainConfig struct { + HomeChainSel uint64 + RMNStaticConfig rmn_home.RMNHomeStaticConfig + RMNDynamicConfig rmn_home.RMNHomeDynamicConfig + NodeOperators []capabilities_registry.CapabilitiesRegistryNodeOperator + NodeP2PIDsPerNodeOpAdmin map[string][][32]byte +} + +func (c DeployHomeChainConfig) Validate() error { + if c.HomeChainSel == 0 { + return fmt.Errorf("home chain selector must be set") + } + if c.RMNDynamicConfig.OffchainConfig == nil { + return fmt.Errorf("offchain config for RMNHomeDynamicConfig must be set") + } + if c.RMNStaticConfig.OffchainConfig == nil { + return fmt.Errorf("offchain config for RMNHomeStaticConfig must be set") + } + if len(c.NodeOperators) == 0 { + return fmt.Errorf("node operators must be set") + } + for _, nop := range c.NodeOperators { + if nop.Admin == (common.Address{}) { + return fmt.Errorf("node operator admin address must be set") + } + if nop.Name == "" { + return fmt.Errorf("node operator name must be set") + } + if len(c.NodeP2PIDsPerNodeOpAdmin[nop.Name]) == 0 { + return fmt.Errorf("node operator %s must have node p2p ids provided", nop.Name) + } + } + + return nil +} + +// deployCapReg deploys the CapabilitiesRegistry contract if it is not already deployed +// and returns a deployment.ContractDeploy struct with the address and contract instance. +func deployCapReg( + lggr logger.Logger, + state CCIPOnChainState, + ab deployment.AddressBook, + chain deployment.Chain, +) (*deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { + homeChainState, exists := state.Chains[chain.Selector] + if exists { + cr := homeChainState.CapabilityRegistry + if cr != nil { + lggr.Infow("Found CapabilitiesRegistry in chain state", "address", cr.Address().String()) + return &deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ + Address: cr.Address(), Contract: cr, Tv: deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0), + }, nil + } + } + capReg, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { + crAddr, tx, cr, err2 := capabilities_registry.DeployCapabilitiesRegistry( + chain.DeployerKey, + chain.Client, + ) + return deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ + Address: crAddr, Contract: cr, Tv: deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0), Tx: tx, Err: err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy capreg", "chain", chain.String(), "err", err) + return nil, err + } + return capReg, nil +} + +func deployHomeChain( + lggr logger.Logger, + e deployment.Environment, + ab deployment.AddressBook, + chain deployment.Chain, + rmnHomeStatic rmn_home.RMNHomeStaticConfig, + rmnHomeDynamic rmn_home.RMNHomeDynamicConfig, + nodeOps []capabilities_registry.CapabilitiesRegistryNodeOperator, + nodeP2PIDsPerNodeOpAdmin map[string][][32]byte, +) (*deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { + // load existing state + state, err := LoadOnchainState(e) + if err != nil { + return nil, fmt.Errorf("failed to load onchain state: %w", err) + } + // Deploy CapabilitiesRegistry, CCIPHome, RMNHome + capReg, err := deployCapReg(lggr, state, ab, chain) + if err != nil { + return nil, err + } + + lggr.Infow("deployed/connected to capreg", "addr", capReg.Address) + ccipHome, err := deployment.DeployContract( + lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*ccip_home.CCIPHome] { + ccAddr, tx, cc, err2 := ccip_home.DeployCCIPHome( + chain.DeployerKey, + chain.Client, + capReg.Address, + ) + return deployment.ContractDeploy[*ccip_home.CCIPHome]{ + Address: ccAddr, Tv: deployment.NewTypeAndVersion(CCIPHome, deployment.Version1_6_0_dev), Tx: tx, Err: err2, Contract: cc, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy CCIPHome", "chain", chain.String(), "err", err) + return nil, err + } + + rmnHome, err := deployment.DeployContract( + lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*rmn_home.RMNHome] { + rmnAddr, tx, rmn, err2 := rmn_home.DeployRMNHome( + chain.DeployerKey, + chain.Client, + ) + return deployment.ContractDeploy[*rmn_home.RMNHome]{ + Address: rmnAddr, Tv: deployment.NewTypeAndVersion(RMNHome, deployment.Version1_6_0_dev), Tx: tx, Err: err2, Contract: rmn, + } + }, + ) + if err != nil { + lggr.Errorw("Failed to deploy RMNHome", "chain", chain.String(), "err", err) + return nil, err + } + + // considering the RMNHome is recently deployed, there is no digest to overwrite + tx, err := rmnHome.Contract.SetCandidate(chain.DeployerKey, rmnHomeStatic, rmnHomeDynamic, [32]byte{}) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + lggr.Errorw("Failed to set candidate on RMNHome", "err", err) + return nil, err + } + + rmnCandidateDigest, err := rmnHome.Contract.GetCandidateDigest(nil) + if err != nil { + lggr.Errorw("Failed to get RMNHome candidate digest", "chain", chain.String(), "err", err) + return nil, err + } + + tx, err = rmnHome.Contract.PromoteCandidateAndRevokeActive(chain.DeployerKey, rmnCandidateDigest, [32]byte{}) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + lggr.Errorw("Failed to promote candidate and revoke active on RMNHome", "chain", chain.String(), "err", err) + return nil, err + } + + rmnActiveDigest, err := rmnHome.Contract.GetActiveDigest(nil) + if err != nil { + lggr.Errorw("Failed to get RMNHome active digest", "chain", chain.String(), "err", err) + return nil, err + } + lggr.Infow("Got rmn home active digest", "digest", rmnActiveDigest) + + if rmnActiveDigest != rmnCandidateDigest { + lggr.Errorw("RMNHome active digest does not match previously candidate digest", + "active", rmnActiveDigest, "candidate", rmnCandidateDigest) + return nil, errors.New("RMNHome active digest does not match candidate digest") + } + + tx, err = capReg.Contract.AddCapabilities(chain.DeployerKey, []capabilities_registry.CapabilitiesRegistryCapability{ + { + LabelledName: internal.CapabilityLabelledName, + Version: internal.CapabilityVersion, + CapabilityType: 2, // consensus. not used (?) + ResponseType: 0, // report. not used (?) + ConfigurationContract: ccipHome.Address, + }, + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + lggr.Errorw("Failed to add capabilities", "chain", chain.String(), "err", err) + return nil, err + } + + tx, err = capReg.Contract.AddNodeOperators(chain.DeployerKey, nodeOps) + txBlockNum, err := deployment.ConfirmIfNoError(chain, tx, err) + if err != nil { + lggr.Errorw("Failed to add node operators", "chain", chain.String(), "err", err) + return nil, err + } + addedEvent, err := capReg.Contract.FilterNodeOperatorAdded(&bind.FilterOpts{ + Start: txBlockNum, + Context: context.Background(), + }, nil, nil) + if err != nil { + lggr.Errorw("Failed to filter NodeOperatorAdded event", "chain", chain.String(), "err", err) + return capReg, err + } + // Need to fetch nodeoperators ids to be able to add nodes for corresponding node operators + p2pIDsByNodeOpId := make(map[uint32][][32]byte) + for addedEvent.Next() { + for nopName, p2pId := range nodeP2PIDsPerNodeOpAdmin { + if addedEvent.Event.Name == nopName { + lggr.Infow("Added node operator", "admin", addedEvent.Event.Admin, "name", addedEvent.Event.Name) + p2pIDsByNodeOpId[addedEvent.Event.NodeOperatorId] = p2pId + } + } + } + if len(p2pIDsByNodeOpId) != len(nodeP2PIDsPerNodeOpAdmin) { + lggr.Errorw("Failed to add all node operators", "added", maps.Keys(p2pIDsByNodeOpId), "expected", maps.Keys(nodeP2PIDsPerNodeOpAdmin), "chain", chain.String()) + return capReg, errors.New("failed to add all node operators") + } + // Adds initial set of nodes to CR, who all have the CCIP capability + if err := addNodes(lggr, capReg.Contract, chain, p2pIDsByNodeOpId); err != nil { + return capReg, err + } + return capReg, nil +} + +func isEqualCapabilitiesRegistryNodeParams(a, b capabilities_registry.CapabilitiesRegistryNodeParams) (bool, error) { + aBytes, err := json.Marshal(a) + if err != nil { + return false, err + } + bBytes, err := json.Marshal(b) + if err != nil { + return false, err + } + return bytes.Equal(aBytes, bBytes), nil +} + +func addNodes( + lggr logger.Logger, + capReg *capabilities_registry.CapabilitiesRegistry, + chain deployment.Chain, + p2pIDsByNodeOpId map[uint32][][32]byte, +) error { + var nodeParams []capabilities_registry.CapabilitiesRegistryNodeParams + nodes, err := capReg.GetNodes(nil) + if err != nil { + return err + } + existingNodeParams := make(map[p2ptypes.PeerID]capabilities_registry.CapabilitiesRegistryNodeParams) + for _, node := range nodes { + existingNodeParams[node.P2pId] = capabilities_registry.CapabilitiesRegistryNodeParams{ + NodeOperatorId: node.NodeOperatorId, + Signer: node.Signer, + P2pId: node.P2pId, + HashedCapabilityIds: node.HashedCapabilityIds, + } + } + for nopID, p2pIDs := range p2pIDsByNodeOpId { + for _, p2pID := range p2pIDs { + // if any p2pIDs are empty throw error + if bytes.Equal(p2pID[:], make([]byte, 32)) { + return errors.Wrapf(errors.New("empty p2pID"), "p2pID: %x selector: %d", p2pID, chain.Selector) + } + nodeParam := capabilities_registry.CapabilitiesRegistryNodeParams{ + NodeOperatorId: nopID, + Signer: p2pID, // Not used in tests + P2pId: p2pID, + EncryptionPublicKey: p2pID, // Not used in tests + HashedCapabilityIds: [][32]byte{internal.CCIPCapabilityID}, + } + if existing, ok := existingNodeParams[p2pID]; ok { + if isEqual, err := isEqualCapabilitiesRegistryNodeParams(existing, nodeParam); err != nil && isEqual { + lggr.Infow("Node already exists", "p2pID", p2pID) + continue + } + } + + nodeParams = append(nodeParams, nodeParam) + } + } + if len(nodeParams) == 0 { + lggr.Infow("No new nodes to add") + return nil + } + tx, err := capReg.AddNodes(chain.DeployerKey, nodeParams) + if err != nil { + lggr.Errorw("Failed to add nodes", "chain", chain.String(), "err", deployment.MaybeDataErr(err)) + return err + } + _, err = chain.Confirm(tx) + return err +} diff --git a/deployment/ccip/changeset/home_chain_test.go b/deployment/ccip/changeset/cs_home_chain_test.go similarity index 89% rename from deployment/ccip/changeset/home_chain_test.go rename to deployment/ccip/changeset/cs_home_chain_test.go index 55bc7466837..a06161f7086 100644 --- a/deployment/ccip/changeset/home_chain_test.go +++ b/deployment/ccip/changeset/cs_home_chain_test.go @@ -3,7 +3,6 @@ package changeset import ( "testing" - chainsel "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" @@ -43,10 +42,7 @@ func TestDeployHomeChain(t *testing.T) { require.NotNil(t, state.Chains[homeChainSel].RMNHome) snap, err := state.View([]uint64{homeChainSel}) require.NoError(t, err) - chainid, err := chainsel.ChainIdFromSelector(homeChainSel) - require.NoError(t, err) - chainName, err := chainsel.NameFromChainId(chainid) - require.NoError(t, err) + chainName := e.Chains[homeChainSel].Name() _, ok := snap[chainName] require.True(t, ok) capRegSnap, ok := snap[chainName].CapabilityRegistry[state.Chains[homeChainSel].CapabilityRegistry.Address().String()] diff --git a/deployment/ccip/changeset/cs_initial_add_chain.go b/deployment/ccip/changeset/cs_initial_add_chain.go new file mode 100644 index 00000000000..13aee106e5a --- /dev/null +++ b/deployment/ccip/changeset/cs_initial_add_chain.go @@ -0,0 +1,463 @@ +package changeset + +import ( + "bytes" + "context" + "encoding/hex" + "fmt" + "os" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink-ccip/chainconfig" + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/common/types" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +) + +var _ deployment.ChangeSet[NewChainsConfig] = ConfigureNewChains + +// ConfigureNewChains enables new chains as destination(s) for CCIP +// It performs the following steps per chain: +// - addChainConfig + AddDON (candidate->primary promotion i.e. init) on the home chain +// - SetOCR3Config on the remote chain +// ConfigureNewChains assumes that the home chain is already enabled and all CCIP contracts are already deployed. +func ConfigureNewChains(env deployment.Environment, c NewChainsConfig) (deployment.ChangesetOutput, error) { + if err := c.Validate(); err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("invalid NewChainsConfig: %w", err) + } + err := configureChain(env, c) + if err != nil { + env.Logger.Errorw("Failed to configure chain", "err", err) + return deployment.ChangesetOutput{}, deployment.MaybeDataErr(err) + } + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{}, + AddressBook: nil, + JobSpecs: nil, + }, nil +} + +type CCIPOCRParams struct { + OCRParameters types.OCRParameters + // Note contains pointers to Arb feeds for prices + CommitOffChainConfig pluginconfig.CommitOffchainConfig + // Note ontains USDC config + ExecuteOffChainConfig pluginconfig.ExecuteOffchainConfig +} + +func (c CCIPOCRParams) Validate() error { + if err := c.OCRParameters.Validate(); err != nil { + return fmt.Errorf("invalid OCR parameters: %w", err) + } + if err := c.CommitOffChainConfig.Validate(); err != nil { + return fmt.Errorf("invalid commit off-chain config: %w", err) + } + if err := c.ExecuteOffChainConfig.Validate(); err != nil { + return fmt.Errorf("invalid execute off-chain config: %w", err) + } + return nil +} + +type NewChainsConfig struct { + // Common to all chains + HomeChainSel uint64 + FeedChainSel uint64 + // Per chain config + ChainConfigByChain map[uint64]CCIPOCRParams +} + +func (c NewChainsConfig) Chains() []uint64 { + chains := make([]uint64, 0, len(c.ChainConfigByChain)) + for chain := range c.ChainConfigByChain { + chains = append(chains, chain) + } + return chains +} + +func (c NewChainsConfig) Validate() error { + if err := deployment.IsValidChainSelector(c.HomeChainSel); err != nil { + return fmt.Errorf("invalid home chain selector: %d - %w", c.HomeChainSel, err) + } + if err := deployment.IsValidChainSelector(c.FeedChainSel); err != nil { + return fmt.Errorf("invalid feed chain selector: %d - %w", c.FeedChainSel, err) + } + // Validate chain config + for chain, cfg := range c.ChainConfigByChain { + if err := cfg.Validate(); err != nil { + return fmt.Errorf("invalid OCR params for chain %d: %w", chain, err) + } + if cfg.CommitOffChainConfig.PriceFeedChainSelector != ccipocr3.ChainSelector(c.FeedChainSel) { + return fmt.Errorf("chain %d has invalid feed chain selector", chain) + } + } + return nil +} + +// DefaultOCRParams returns the default OCR parameters for a chain, +// except for a few values which must be parameterized (passed as arguments). +func DefaultOCRParams( + feedChainSel uint64, + tokenInfo map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo, + tokenDataObservers []pluginconfig.TokenDataObserverConfig, +) CCIPOCRParams { + return CCIPOCRParams{ + OCRParameters: types.OCRParameters{ + DeltaProgress: internal.DeltaProgress, + DeltaResend: internal.DeltaResend, + DeltaInitial: internal.DeltaInitial, + DeltaRound: internal.DeltaRound, + DeltaGrace: internal.DeltaGrace, + DeltaCertifiedCommitRequest: internal.DeltaCertifiedCommitRequest, + DeltaStage: internal.DeltaStage, + Rmax: internal.Rmax, + MaxDurationQuery: internal.MaxDurationQuery, + MaxDurationObservation: internal.MaxDurationObservation, + MaxDurationShouldAcceptAttestedReport: internal.MaxDurationShouldAcceptAttestedReport, + MaxDurationShouldTransmitAcceptedReport: internal.MaxDurationShouldTransmitAcceptedReport, + }, + ExecuteOffChainConfig: pluginconfig.ExecuteOffchainConfig{ + BatchGasLimit: internal.BatchGasLimit, + RelativeBoostPerWaitHour: internal.RelativeBoostPerWaitHour, + InflightCacheExpiry: *config.MustNewDuration(internal.InflightCacheExpiry), + RootSnoozeTime: *config.MustNewDuration(internal.RootSnoozeTime), + MessageVisibilityInterval: *config.MustNewDuration(internal.FirstBlockAge), + BatchingStrategyID: internal.BatchingStrategyID, + TokenDataObservers: tokenDataObservers, + }, + CommitOffChainConfig: pluginconfig.CommitOffchainConfig{ + RemoteGasPriceBatchWriteFrequency: *config.MustNewDuration(internal.RemoteGasPriceBatchWriteFrequency), + TokenPriceBatchWriteFrequency: *config.MustNewDuration(internal.TokenPriceBatchWriteFrequency), + TokenInfo: tokenInfo, + PriceFeedChainSelector: ccipocr3.ChainSelector(feedChainSel), + NewMsgScanBatchSize: merklemulti.MaxNumberTreeLeaves, + MaxReportTransmissionCheckAttempts: 5, + RMNEnabled: os.Getenv("ENABLE_RMN") == "true", // only enabled in manual test + RMNSignaturesTimeout: 30 * time.Minute, + MaxMerkleTreeSize: merklemulti.MaxNumberTreeLeaves, + SignObservationPrefix: "chainlink ccip 1.6 rmn observation", + }, + } +} + +// configureChain assumes the all the Home chain contracts and CCIP contracts are deployed +// It does - +// 1. addChainConfig for each chain in CCIPHome +// 2. Registers the nodes with the capability registry +// 3. SetOCR3Config on the remote chain +func configureChain( + e deployment.Environment, + c NewChainsConfig, +) error { + if e.OCRSecrets.IsEmpty() { + return fmt.Errorf("OCR secrets are empty") + } + nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + if err != nil || len(nodes) == 0 { + e.Logger.Errorw("Failed to get node info", "err", err) + return err + } + existingState, err := LoadOnchainState(e) + if err != nil { + e.Logger.Errorw("Failed to load existing onchain state", "err") + return err + } + homeChain := e.Chains[c.HomeChainSel] + capReg := existingState.Chains[c.HomeChainSel].CapabilityRegistry + if capReg == nil { + e.Logger.Errorw("Failed to get capability registry", "chain", homeChain.String()) + return fmt.Errorf("capability registry not found") + } + ccipHome := existingState.Chains[c.HomeChainSel].CCIPHome + if ccipHome == nil { + e.Logger.Errorw("Failed to get ccip home", "chain", homeChain.String(), "err", err) + return fmt.Errorf("ccip home not found") + } + rmnHome := existingState.Chains[c.HomeChainSel].RMNHome + if rmnHome == nil { + e.Logger.Errorw("Failed to get rmn home", "chain", homeChain.String(), "err", err) + return fmt.Errorf("rmn home not found") + } + + for chainSel, chainConfig := range c.ChainConfigByChain { + chain, _ := e.Chains[chainSel] + chainState, ok := existingState.Chains[chain.Selector] + if !ok { + return fmt.Errorf("chain state not found for chain %d", chain.Selector) + } + if chainState.OffRamp == nil { + return fmt.Errorf("off ramp not found for chain %d", chain.Selector) + } + _, err = addChainConfig( + e.Logger, + e.Chains[c.HomeChainSel], + ccipHome, + chain.Selector, + nodes.NonBootstraps().PeerIDs()) + if err != nil { + return err + } + // For each chain, we create a DON on the home chain (2 OCR instances) + if err := addDON( + e.Logger, + e.OCRSecrets, + capReg, + ccipHome, + rmnHome.Address(), + chainState.OffRamp, + chain, + e.Chains[c.HomeChainSel], + nodes.NonBootstraps(), + chainConfig, + ); err != nil { + e.Logger.Errorw("Failed to add DON", "err", err) + return err + } + } + + return nil +} + +func setupConfigInfo(chainSelector uint64, readers [][32]byte, fChain uint8, cfg []byte) ccip_home.CCIPHomeChainConfigArgs { + return ccip_home.CCIPHomeChainConfigArgs{ + ChainSelector: chainSelector, + ChainConfig: ccip_home.CCIPHomeChainConfig{ + Readers: readers, + FChain: fChain, + Config: cfg, + }, + } +} + +func addChainConfig( + lggr logger.Logger, + h deployment.Chain, + ccipConfig *ccip_home.CCIPHome, + chainSelector uint64, + p2pIDs [][32]byte, +) (ccip_home.CCIPHomeChainConfigArgs, error) { + // First Add CCIPOCRParams that includes all p2pIDs as readers + encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ + GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), + DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), + OptimisticConfirmations: 1, + }) + if err != nil { + return ccip_home.CCIPHomeChainConfigArgs{}, err + } + chainConfig := setupConfigInfo(chainSelector, p2pIDs, uint8(len(p2pIDs)/3), encodedExtraChainConfig) + tx, err := ccipConfig.ApplyChainConfigUpdates(h.DeployerKey, nil, []ccip_home.CCIPHomeChainConfigArgs{ + chainConfig, + }) + if _, err := deployment.ConfirmIfNoError(h, tx, err); err != nil { + return ccip_home.CCIPHomeChainConfigArgs{}, err + } + lggr.Infow("Applied chain config updates", "homeChain", h.String(), "addedChain", chainSelector, "chainConfig", chainConfig) + return chainConfig, nil +} + +// createDON creates one DON with 2 plugins (commit and exec) +// It first set a new candidate for the DON with the first plugin type and AddDON on capReg +// Then for subsequent operations it uses UpdateDON to promote the first plugin to the active deployment +// and to set candidate and promote it for the second plugin +func createDON( + lggr logger.Logger, + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + ocr3Configs map[cctypes.PluginType]ccip_home.CCIPHomeOCR3Config, + home deployment.Chain, + newChainSel uint64, + nodes deployment.Nodes, +) error { + commitConfig, ok := ocr3Configs[cctypes.PluginTypeCCIPCommit] + if !ok { + return fmt.Errorf("missing commit plugin in ocr3Configs") + } + + execConfig, ok := ocr3Configs[cctypes.PluginTypeCCIPExec] + if !ok { + return fmt.Errorf("missing exec plugin in ocr3Configs") + } + + latestDon, err := internal.LatestCCIPDON(capReg) + if err != nil { + return err + } + + donID := latestDon.Id + 1 + + err = internal.SetupCommitDON(lggr, donID, commitConfig, capReg, home, nodes, ccipHome) + if err != nil { + return fmt.Errorf("setup commit don: %w", err) + } + + // TODO: bug in contract causing this to not work as expected. + err = internal.SetupExecDON(lggr, donID, execConfig, capReg, home, nodes, ccipHome) + if err != nil { + return fmt.Errorf("setup exec don: %w", err) + } + return ValidateCCIPHomeConfigSetUp(lggr, capReg, ccipHome, newChainSel) +} + +func addDON( + lggr logger.Logger, + ocrSecrets deployment.OCRSecrets, + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + rmnHomeAddress common.Address, + offRamp *offramp.OffRamp, + dest deployment.Chain, + home deployment.Chain, + nodes deployment.Nodes, + ocrParams CCIPOCRParams, +) error { + ocrConfigs, err := internal.BuildOCR3ConfigForCCIPHome( + ocrSecrets, offRamp, dest, nodes, rmnHomeAddress, ocrParams.OCRParameters, ocrParams.CommitOffChainConfig, ocrParams.ExecuteOffChainConfig) + if err != nil { + return err + } + err = createDON(lggr, capReg, ccipHome, ocrConfigs, home, dest.Selector, nodes) + if err != nil { + return err + } + don, err := internal.LatestCCIPDON(capReg) + if err != nil { + return err + } + lggr.Infow("Added DON", "donID", don.Id) + + offrampOCR3Configs, err := internal.BuildSetOCR3ConfigArgs(don.Id, ccipHome, dest.Selector) + if err != nil { + return err + } + lggr.Infow("Setting OCR3 Configs", + "offrampOCR3Configs", offrampOCR3Configs, + "configDigestCommit", hex.EncodeToString(offrampOCR3Configs[cctypes.PluginTypeCCIPCommit].ConfigDigest[:]), + "configDigestExec", hex.EncodeToString(offrampOCR3Configs[cctypes.PluginTypeCCIPExec].ConfigDigest[:]), + "chainSelector", dest.Selector, + ) + + tx, err := offRamp.SetOCR3Configs(dest.DeployerKey, offrampOCR3Configs) + if _, err := deployment.ConfirmIfNoError(dest, tx, err); err != nil { + return err + } + + mapOfframpOCR3Configs := make(map[cctypes.PluginType]offramp.MultiOCR3BaseOCRConfigArgs) + for _, config := range offrampOCR3Configs { + mapOfframpOCR3Configs[cctypes.PluginType(config.OcrPluginType)] = config + } + + for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { + ocrConfig, err := offRamp.LatestConfigDetails(&bind.CallOpts{ + Context: context.Background(), + }, uint8(pluginType)) + if err != nil { + return err + } + lggr.Debugw("Fetched OCR3 Configs", + "MultiOCR3BaseOCRConfig.F", ocrConfig.ConfigInfo.F, + "MultiOCR3BaseOCRConfig.N", ocrConfig.ConfigInfo.N, + "MultiOCR3BaseOCRConfig.IsSignatureVerificationEnabled", ocrConfig.ConfigInfo.IsSignatureVerificationEnabled, + "Signers", ocrConfig.Signers, + "Transmitters", ocrConfig.Transmitters, + "configDigest", hex.EncodeToString(ocrConfig.ConfigInfo.ConfigDigest[:]), + "chain", dest.String(), + ) + // TODO: assertions to be done as part of full state + // resprentation validation CCIP-3047 + if mapOfframpOCR3Configs[pluginType].ConfigDigest != ocrConfig.ConfigInfo.ConfigDigest { + return fmt.Errorf("%s OCR3 config digest mismatch", pluginType.String()) + } + if mapOfframpOCR3Configs[pluginType].F != ocrConfig.ConfigInfo.F { + return fmt.Errorf("%s OCR3 config F mismatch", pluginType.String()) + } + if mapOfframpOCR3Configs[pluginType].IsSignatureVerificationEnabled != ocrConfig.ConfigInfo.IsSignatureVerificationEnabled { + return fmt.Errorf("%s OCR3 config signature verification mismatch", pluginType.String()) + } + if pluginType == cctypes.PluginTypeCCIPCommit { + // only commit will set signers, exec doesn't need them. + for i, signer := range mapOfframpOCR3Configs[pluginType].Signers { + if !bytes.Equal(signer.Bytes(), ocrConfig.Signers[i].Bytes()) { + return fmt.Errorf("%s OCR3 config signer mismatch", pluginType.String()) + } + } + } + for i, transmitter := range mapOfframpOCR3Configs[pluginType].Transmitters { + if !bytes.Equal(transmitter.Bytes(), ocrConfig.Transmitters[i].Bytes()) { + return fmt.Errorf("%s OCR3 config transmitter mismatch", pluginType.String()) + } + } + } + + return nil +} + +// ValidateCCIPHomeConfigSetUp checks that the commit and exec active and candidate configs are set up correctly +func ValidateCCIPHomeConfigSetUp( + lggr logger.Logger, + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + chainSel uint64, +) error { + // fetch DONID + donID, err := internal.DonIDForChain(capReg, ccipHome, chainSel) + if err != nil { + return fmt.Errorf("fetch don id for chain: %w", err) + } + // final sanity checks on configs. + commitConfigs, err := ccipHome.GetAllConfigs(&bind.CallOpts{ + //Pending: true, + }, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get all commit configs: %w", err) + } + commitActiveDigest, err := ccipHome.GetActiveDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get active commit digest: %w", err) + } + lggr.Debugw("Fetched active commit digest", "commitActiveDigest", hex.EncodeToString(commitActiveDigest[:])) + commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get commit candidate digest: %w", err) + } + lggr.Debugw("Fetched candidate commit digest", "commitCandidateDigest", hex.EncodeToString(commitCandidateDigest[:])) + if commitConfigs.ActiveConfig.ConfigDigest == [32]byte{} { + return fmt.Errorf( + "active config digest is empty for commit, expected nonempty, donID: %d, cfg: %+v, config digest from GetActiveDigest call: %x, config digest from GetCandidateDigest call: %x", + donID, commitConfigs.ActiveConfig, commitActiveDigest, commitCandidateDigest) + } + if commitConfigs.CandidateConfig.ConfigDigest != [32]byte{} { + return fmt.Errorf( + "candidate config digest is nonempty for commit, expected empty, donID: %d, cfg: %+v, config digest from GetCandidateDigest call: %x, config digest from GetActiveDigest call: %x", + donID, commitConfigs.CandidateConfig, commitCandidateDigest, commitActiveDigest) + } + + execConfigs, err := ccipHome.GetAllConfigs(nil, donID, uint8(cctypes.PluginTypeCCIPExec)) + if err != nil { + return fmt.Errorf("get all exec configs: %w", err) + } + lggr.Debugw("Fetched exec configs", + "ActiveConfig.ConfigDigest", hex.EncodeToString(execConfigs.ActiveConfig.ConfigDigest[:]), + "CandidateConfig.ConfigDigest", hex.EncodeToString(execConfigs.CandidateConfig.ConfigDigest[:]), + ) + if execConfigs.ActiveConfig.ConfigDigest == [32]byte{} { + return fmt.Errorf("active config digest is empty for exec, expected nonempty, cfg: %v", execConfigs.ActiveConfig) + } + if execConfigs.CandidateConfig.ConfigDigest != [32]byte{} { + return fmt.Errorf("candidate config digest is nonempty for exec, expected empty, cfg: %v", execConfigs.CandidateConfig) + } + return nil +} diff --git a/deployment/ccip/changeset/jobs.go b/deployment/ccip/changeset/cs_jobspec.go similarity index 73% rename from deployment/ccip/changeset/jobs.go rename to deployment/ccip/changeset/cs_jobspec.go index 3a5b0e294d8..2551f193f47 100644 --- a/deployment/ccip/changeset/jobs.go +++ b/deployment/ccip/changeset/cs_jobspec.go @@ -1,25 +1,28 @@ package changeset import ( + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" "github.com/smartcontractkit/chainlink/v2/core/services/relay" ) -// In our case, the only address needed is the cap registry which is actually an env var. -// and will pre-exist for our deployment. So the job specs only depend on the environment operators. -func NewCCIPJobSpecs(nodeIds []string, oc deployment.OffchainClient) (map[string][]string, error) { - nodes, err := deployment.NodeInfo(nodeIds, oc) +var _ deployment.ChangeSet[any] = CCIPCapabilityJobspec + +// CCIPCapabilityJobspec returns the job specs for the CCIP capability. +// The caller needs to propose these job specs to the offchain system. +func CCIPCapabilityJobspec(env deployment.Environment, _ any) (deployment.ChangesetOutput, error) { + nodes, err := deployment.NodeInfo(env.NodeIDs, env.Offchain) if err != nil { - return nil, err + return deployment.ChangesetOutput{}, err } // Generate a set of brand new job specs for CCIP for a specific environment // (including NOPs) and new addresses. // We want to assign one CCIP capability job to each node. And node with // an addr we'll list as bootstrapper. // Find the bootstrap nodes - nodesToJobSpecs := make(map[string][]string) for _, node := range nodes { var spec string @@ -50,9 +53,13 @@ func NewCCIPJobSpecs(nodeIds []string, oc deployment.OffchainClient) (map[string }) } if err != nil { - return nil, err + return deployment.ChangesetOutput{}, err } nodesToJobSpecs[node.NodeID] = append(nodesToJobSpecs[node.NodeID], spec) } - return nodesToJobSpecs, nil + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{}, + AddressBook: nil, + JobSpecs: nodesToJobSpecs, + }, nil } diff --git a/deployment/ccip/changeset/jobspec_test.go b/deployment/ccip/changeset/cs_jobspec_test.go similarity index 100% rename from deployment/ccip/changeset/jobspec_test.go rename to deployment/ccip/changeset/cs_jobspec_test.go diff --git a/deployment/ccip/changeset/cs_prerequisites.go b/deployment/ccip/changeset/cs_prerequisites.go new file mode 100644 index 00000000000..2386d3bb784 --- /dev/null +++ b/deployment/ccip/changeset/cs_prerequisites.go @@ -0,0 +1,308 @@ +package changeset + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "golang.org/x/sync/errgroup" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/registry_module_owner_custom" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/multicall3" +) + +var ( + _ deployment.ChangeSet[DeployPrerequisiteConfig] = DeployPrerequisites +) + +// DeployPrerequisites deploys the pre-requisite contracts for CCIP +// pre-requisite contracts are the contracts which can be reused from previous versions of CCIP +// Or the contracts which are already deployed on the chain ( for example, tokens, feeds, etc) +// Caller should update the environment's address book with the returned addresses. +func DeployPrerequisites(env deployment.Environment, cfg DeployPrerequisiteConfig) (deployment.ChangesetOutput, error) { + err := cfg.Validate() + if err != nil { + return deployment.ChangesetOutput{}, errors.Wrapf(deployment.ErrInvalidConfig, "%v", err) + } + ab := deployment.NewMemoryAddressBook() + err = deployPrerequisiteChainContracts(env, ab, cfg.ChainSelectors, cfg.Opts...) + if err != nil { + env.Logger.Errorw("Failed to deploy prerequisite contracts", "err", err, "addressBook", ab) + return deployment.ChangesetOutput{ + AddressBook: ab, + }, fmt.Errorf("failed to deploy prerequisite contracts: %w", err) + } + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{}, + AddressBook: ab, + JobSpecs: nil, + }, nil +} + +type DeployPrerequisiteContractsOpts struct { + USDCEnabledChains []uint64 + Multicall3Enabled bool +} + +type DeployPrerequisiteConfig struct { + ChainSelectors []uint64 + Opts []PrerequisiteOpt + // TODO handle tokens and feeds in prerequisite config + Tokens map[TokenSymbol]common.Address + Feeds map[TokenSymbol]common.Address +} + +func (c DeployPrerequisiteConfig) Validate() error { + mapAllChainSelectors := make(map[uint64]struct{}) + for _, cs := range c.ChainSelectors { + mapAllChainSelectors[cs] = struct{}{} + if err := deployment.IsValidChainSelector(cs); err != nil { + return fmt.Errorf("invalid chain selector: %d - %w", cs, err) + } + } + return nil +} + +type PrerequisiteOpt func(o *DeployPrerequisiteContractsOpts) + +func WithUSDCChains(chains []uint64) PrerequisiteOpt { + return func(o *DeployPrerequisiteContractsOpts) { + o.USDCEnabledChains = chains + } +} + +func WithMulticall3(enabled bool) PrerequisiteOpt { + return func(o *DeployPrerequisiteContractsOpts) { + o.Multicall3Enabled = enabled + } +} + +func deployPrerequisiteChainContracts(e deployment.Environment, ab deployment.AddressBook, selectors []uint64, opts ...PrerequisiteOpt) error { + state, err := LoadOnchainState(e) + if err != nil { + e.Logger.Errorw("Failed to load existing onchain state", "err") + return err + } + deployGrp := errgroup.Group{} + for _, sel := range selectors { + chain := e.Chains[sel] + deployGrp.Go(func() error { + err := deployPrerequisiteContracts(e, ab, state, chain, opts...) + if err != nil { + e.Logger.Errorw("Failed to deploy prerequisite contracts", "chain", sel, "err", err) + return err + } + return nil + }) + } + return deployGrp.Wait() +} + +// deployPrerequisiteContracts deploys the contracts that can be ported from previous CCIP version to the new one. +// This is only required for staging and test environments where the contracts are not already deployed. +func deployPrerequisiteContracts(e deployment.Environment, ab deployment.AddressBook, state CCIPOnChainState, chain deployment.Chain, opts ...PrerequisiteOpt) error { + deployOpts := &DeployPrerequisiteContractsOpts{} + for _, opt := range opts { + if opt != nil { + opt(deployOpts) + } + } + var isUSDC bool + for _, sel := range deployOpts.USDCEnabledChains { + if sel == chain.Selector { + isUSDC = true + break + } + } + lggr := e.Logger + chainState, chainExists := state.Chains[chain.Selector] + var weth9Contract *weth9.WETH9 + var tokenAdminReg *token_admin_registry.TokenAdminRegistry + var registryModule *registry_module_owner_custom.RegistryModuleOwnerCustom + var rmnProxy *rmn_proxy_contract.RMNProxyContract + var r *router.Router + var mc3 *multicall3.Multicall3 + if chainExists { + weth9Contract = chainState.Weth9 + tokenAdminReg = chainState.TokenAdminRegistry + registryModule = chainState.RegistryModule + rmnProxy = chainState.RMNProxyExisting + r = chainState.Router + mc3 = chainState.Multicall3 + } + if rmnProxy == nil { + // we want to replicate the mainnet scenario where RMNProxy is already deployed with some existing RMN + // This will need us to use two different RMNProxy contracts + // 1. RMNProxyNew with RMNRemote - ( deployed later in chain contracts) + // 2. RMNProxyExisting with mockRMN - ( deployed here, replicating the behavior of existing RMNProxy with already set RMN) + rmn, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*mock_rmn_contract.MockRMNContract] { + rmnAddr, tx2, rmn, err2 := mock_rmn_contract.DeployMockRMNContract( + chain.DeployerKey, + chain.Client, + ) + return deployment.ContractDeploy[*mock_rmn_contract.MockRMNContract]{ + rmnAddr, rmn, tx2, deployment.NewTypeAndVersion(MockRMN, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy mock RMN", "chain", chain.String(), "err", err) + return err + } + rmnProxyContract, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract] { + rmnProxyAddr, tx2, rmnProxy, err2 := rmn_proxy_contract.DeployRMNProxyContract( + chain.DeployerKey, + chain.Client, + rmn.Address, + ) + return deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract]{ + rmnProxyAddr, rmnProxy, tx2, deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy RMNProxyExisting", "chain", chain.String(), "err", err) + return err + } + rmnProxy = rmnProxyContract.Contract + } + if tokenAdminReg == nil { + tokenAdminRegistry, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*token_admin_registry.TokenAdminRegistry] { + tokenAdminRegistryAddr, tx2, tokenAdminRegistry, err2 := token_admin_registry.DeployTokenAdminRegistry( + chain.DeployerKey, + chain.Client) + return deployment.ContractDeploy[*token_admin_registry.TokenAdminRegistry]{ + tokenAdminRegistryAddr, tokenAdminRegistry, tx2, deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy token admin registry", "chain", chain.String(), "err", err) + return err + } + tokenAdminReg = tokenAdminRegistry.Contract + } else { + e.Logger.Infow("tokenAdminRegistry already deployed", "chain", chain.String(), "addr", tokenAdminReg.Address) + } + if registryModule == nil { + customRegistryModule, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom] { + regModAddr, tx2, regMod, err2 := registry_module_owner_custom.DeployRegistryModuleOwnerCustom( + chain.DeployerKey, + chain.Client, + tokenAdminReg.Address()) + return deployment.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom]{ + regModAddr, regMod, tx2, deployment.NewTypeAndVersion(RegistryModule, deployment.Version1_5_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy custom registry module", "chain", chain.String(), "err", err) + return err + } + registryModule = customRegistryModule.Contract + } else { + e.Logger.Infow("custom registry module already deployed", "chain", chain.String(), "addr", registryModule.Address) + } + isRegistryAdded, err := tokenAdminReg.IsRegistryModule(nil, registryModule.Address()) + if err != nil { + e.Logger.Errorw("Failed to check if registry module is added on token admin registry", "chain", chain.String(), "err", err) + return fmt.Errorf("failed to check if registry module is added on token admin registry: %w", err) + } + if !isRegistryAdded { + tx, err := tokenAdminReg.AddRegistryModule(chain.DeployerKey, registryModule.Address()) + if err != nil { + e.Logger.Errorw("Failed to assign registry module on token admin registry", "chain", chain.String(), "err", err) + return fmt.Errorf("failed to assign registry module on token admin registry: %w", err) + } + + _, err = chain.Confirm(tx) + if err != nil { + e.Logger.Errorw("Failed to confirm assign registry module on token admin registry", "chain", chain.String(), "err", err) + return fmt.Errorf("failed to confirm assign registry module on token admin registry: %w", err) + } + e.Logger.Infow("assigned registry module on token admin registry") + } + if weth9Contract == nil { + weth, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*weth9.WETH9] { + weth9Addr, tx2, weth9c, err2 := weth9.DeployWETH9( + chain.DeployerKey, + chain.Client, + ) + return deployment.ContractDeploy[*weth9.WETH9]{ + weth9Addr, weth9c, tx2, deployment.NewTypeAndVersion(WETH9, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy weth9", "chain", chain.String(), "err", err) + return err + } + weth9Contract = weth.Contract + } else { + lggr.Infow("weth9 already deployed", "addr", weth9Contract.Address) + } + // if router is not already deployed, we deploy it + if r == nil { + routerContract, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*router.Router] { + routerAddr, tx2, routerC, err2 := router.DeployRouter( + chain.DeployerKey, + chain.Client, + weth9Contract.Address(), + rmnProxy.Address(), + ) + return deployment.ContractDeploy[*router.Router]{ + routerAddr, routerC, tx2, deployment.NewTypeAndVersion(Router, deployment.Version1_2_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy router", "chain", chain.String(), "err", err) + return err + } + + r = routerContract.Contract + } else { + e.Logger.Infow("router already deployed", "chain", chain.String(), "addr", chainState.Router.Address) + } + if deployOpts.Multicall3Enabled && mc3 == nil { + _, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*multicall3.Multicall3] { + multicall3Addr, tx2, multicall3Wrapper, err2 := multicall3.DeployMulticall3( + chain.DeployerKey, + chain.Client, + ) + return deployment.ContractDeploy[*multicall3.Multicall3]{ + multicall3Addr, multicall3Wrapper, tx2, deployment.NewTypeAndVersion(Multicall3, deployment.Version1_0_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy ccip multicall", "chain", chain.String(), "err", err) + return err + } + } else { + if mc3 != nil { + e.Logger.Info("ccip multicall already deployed", "chain", chain.String(), "addr", mc3.Address) + } + } + if isUSDC { + token, pool, messenger, transmitter, err1 := DeployUSDC(e.Logger, chain, ab, rmnProxy.Address(), r.Address()) + if err1 != nil { + return err1 + } + e.Logger.Infow("Deployed USDC contracts", + "chain", chain.String(), + "token", token.Address(), + "pool", pool.Address(), + "transmitter", transmitter.Address(), + "messenger", messenger.Address(), + ) + } + return nil +} diff --git a/deployment/ccip/changeset/prerequisites_test.go b/deployment/ccip/changeset/cs_prerequisites_test.go similarity index 95% rename from deployment/ccip/changeset/prerequisites_test.go rename to deployment/ccip/changeset/cs_prerequisites_test.go index 1a167b2816c..da1ff9c83a9 100644 --- a/deployment/ccip/changeset/prerequisites_test.go +++ b/deployment/ccip/changeset/cs_prerequisites_test.go @@ -28,7 +28,6 @@ func TestDeployPrerequisites(t *testing.T) { require.NoError(t, err) state, err := LoadOnchainState(e) require.NoError(t, err) - require.NotNil(t, state.Chains[newChain].LinkToken) require.NotNil(t, state.Chains[newChain].Weth9) require.NotNil(t, state.Chains[newChain].TokenAdminRegistry) require.NotNil(t, state.Chains[newChain].RegistryModule) diff --git a/deployment/ccip/changeset/deploy.go b/deployment/ccip/changeset/deploy.go deleted file mode 100644 index 3aa654862dc..00000000000 --- a/deployment/ccip/changeset/deploy.go +++ /dev/null @@ -1,829 +0,0 @@ -package changeset - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "golang.org/x/sync/errgroup" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/registry_module_owner_custom" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/multicall3" -) - -var ( - MockRMN deployment.ContractType = "MockRMN" - RMNRemote deployment.ContractType = "RMNRemote" - LinkToken deployment.ContractType = "LinkToken" - ARMProxy deployment.ContractType = "ARMProxy" - WETH9 deployment.ContractType = "WETH9" - Router deployment.ContractType = "Router" - CommitStore deployment.ContractType = "CommitStore" - TokenAdminRegistry deployment.ContractType = "TokenAdminRegistry" - RegistryModule deployment.ContractType = "RegistryModuleOwnerCustom" - NonceManager deployment.ContractType = "NonceManager" - FeeQuoter deployment.ContractType = "FeeQuoter" - CCIPHome deployment.ContractType = "CCIPHome" - CCIPConfig deployment.ContractType = "CCIPConfig" - RMNHome deployment.ContractType = "RMNHome" - OnRamp deployment.ContractType = "OnRamp" - OffRamp deployment.ContractType = "OffRamp" - CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" - PriceFeed deployment.ContractType = "PriceFeed" - // Note test router maps to a regular router contract. - TestRouter deployment.ContractType = "TestRouter" - Multicall3 deployment.ContractType = "Multicall3" - CCIPReceiver deployment.ContractType = "CCIPReceiver" - BurnMintToken deployment.ContractType = "BurnMintToken" - BurnMintTokenPool deployment.ContractType = "BurnMintTokenPool" - USDCToken deployment.ContractType = "USDCToken" - USDCMockTransmitter deployment.ContractType = "USDCMockTransmitter" - USDCTokenMessenger deployment.ContractType = "USDCTokenMessenger" - USDCTokenPool deployment.ContractType = "USDCTokenPool" -) - -type DeployPrerequisiteContractsOpts struct { - USDCEnabledChains []uint64 - Multicall3Enabled bool -} - -type PrerequisiteOpt func(o *DeployPrerequisiteContractsOpts) - -func WithUSDCChains(chains []uint64) PrerequisiteOpt { - return func(o *DeployPrerequisiteContractsOpts) { - o.USDCEnabledChains = chains - } -} - -func WithMulticall3(enabled bool) PrerequisiteOpt { - return func(o *DeployPrerequisiteContractsOpts) { - o.Multicall3Enabled = enabled - } -} - -func deployPrerequisiteChainContracts(e deployment.Environment, ab deployment.AddressBook, selectors []uint64, opts ...PrerequisiteOpt) error { - state, err := LoadOnchainState(e) - if err != nil { - e.Logger.Errorw("Failed to load existing onchain state", "err") - return err - } - deployGrp := errgroup.Group{} - for _, sel := range selectors { - chain := e.Chains[sel] - deployGrp.Go(func() error { - err := deployPrerequisiteContracts(e, ab, state, chain, opts...) - if err != nil { - e.Logger.Errorw("Failed to deploy prerequisite contracts", "chain", sel, "err", err) - return err - } - return nil - }) - } - return deployGrp.Wait() -} - -// deployPrerequisiteContracts deploys the contracts that can be ported from previous CCIP version to the new one. -// This is only required for staging and test environments where the contracts are not already deployed. -func deployPrerequisiteContracts(e deployment.Environment, ab deployment.AddressBook, state CCIPOnChainState, chain deployment.Chain, opts ...PrerequisiteOpt) error { - deployOpts := &DeployPrerequisiteContractsOpts{} - for _, opt := range opts { - if opt != nil { - opt(deployOpts) - } - } - var isUSDC bool - for _, sel := range deployOpts.USDCEnabledChains { - if sel == chain.Selector { - isUSDC = true - break - } - } - lggr := e.Logger - chainState, chainExists := state.Chains[chain.Selector] - var weth9Contract *weth9.WETH9 - var linkTokenContract *burn_mint_erc677.BurnMintERC677 - var tokenAdminReg *token_admin_registry.TokenAdminRegistry - var registryModule *registry_module_owner_custom.RegistryModuleOwnerCustom - var rmnProxy *rmn_proxy_contract.RMNProxyContract - var r *router.Router - var mc3 *multicall3.Multicall3 - if chainExists { - weth9Contract = chainState.Weth9 - linkTokenContract = chainState.LinkToken - tokenAdminReg = chainState.TokenAdminRegistry - registryModule = chainState.RegistryModule - rmnProxy = chainState.RMNProxyExisting - r = chainState.Router - mc3 = chainState.Multicall3 - } - if rmnProxy == nil { - // we want to replicate the mainnet scenario where RMNProxy is already deployed with some existing RMN - // This will need us to use two different RMNProxy contracts - // 1. RMNProxyNew with RMNRemote - ( deployed later in chain contracts) - // 2. RMNProxyExisting with mockRMN - ( deployed here, replicating the behavior of existing RMNProxy with already set RMN) - rmn, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*mock_rmn_contract.MockRMNContract] { - rmnAddr, tx2, rmn, err2 := mock_rmn_contract.DeployMockRMNContract( - chain.DeployerKey, - chain.Client, - ) - return deployment.ContractDeploy[*mock_rmn_contract.MockRMNContract]{ - rmnAddr, rmn, tx2, deployment.NewTypeAndVersion(MockRMN, deployment.Version1_0_0), err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy mock RMN", "err", err) - return err - } - lggr.Infow("deployed mock RMN", "addr", rmn.Address) - rmnProxyContract, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract] { - rmnProxyAddr, tx2, rmnProxy, err2 := rmn_proxy_contract.DeployRMNProxyContract( - chain.DeployerKey, - chain.Client, - rmn.Address, - ) - return deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract]{ - rmnProxyAddr, rmnProxy, tx2, deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0), err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy RMNProxyNew", "err", err) - return err - } - lggr.Infow("deployed RMNProxyNew", "addr", rmnProxyContract.Address) - rmnProxy = rmnProxyContract.Contract - } - if tokenAdminReg == nil { - tokenAdminRegistry, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*token_admin_registry.TokenAdminRegistry] { - tokenAdminRegistryAddr, tx2, tokenAdminRegistry, err2 := token_admin_registry.DeployTokenAdminRegistry( - chain.DeployerKey, - chain.Client) - return deployment.ContractDeploy[*token_admin_registry.TokenAdminRegistry]{ - tokenAdminRegistryAddr, tokenAdminRegistry, tx2, deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy token admin registry", "err", err) - return err - } - e.Logger.Infow("deployed tokenAdminRegistry", "addr", tokenAdminRegistry) - tokenAdminReg = tokenAdminRegistry.Contract - } else { - e.Logger.Infow("tokenAdminRegistry already deployed", "addr", tokenAdminReg.Address) - } - if registryModule == nil { - customRegistryModule, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom] { - regModAddr, tx2, regMod, err2 := registry_module_owner_custom.DeployRegistryModuleOwnerCustom( - chain.DeployerKey, - chain.Client, - tokenAdminReg.Address()) - return deployment.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom]{ - regModAddr, regMod, tx2, deployment.NewTypeAndVersion(RegistryModule, deployment.Version1_5_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy custom registry module", "err", err) - return err - } - e.Logger.Infow("deployed custom registry module", "addr", customRegistryModule) - registryModule = customRegistryModule.Contract - } else { - e.Logger.Infow("custom registry module already deployed", "addr", registryModule.Address) - } - isRegistryAdded, err := tokenAdminReg.IsRegistryModule(nil, registryModule.Address()) - if err != nil { - e.Logger.Errorw("Failed to check if registry module is added on token admin registry", "err", err) - return fmt.Errorf("failed to check if registry module is added on token admin registry: %w", err) - } - if !isRegistryAdded { - tx, err := tokenAdminReg.AddRegistryModule(chain.DeployerKey, registryModule.Address()) - if err != nil { - e.Logger.Errorw("Failed to assign registry module on token admin registry", "err", err) - return fmt.Errorf("failed to assign registry module on token admin registry: %w", err) - } - - _, err = chain.Confirm(tx) - if err != nil { - e.Logger.Errorw("Failed to confirm assign registry module on token admin registry", "err", err) - return fmt.Errorf("failed to confirm assign registry module on token admin registry: %w", err) - } - e.Logger.Infow("assigned registry module on token admin registry") - } - if weth9Contract == nil { - weth, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*weth9.WETH9] { - weth9Addr, tx2, weth9c, err2 := weth9.DeployWETH9( - chain.DeployerKey, - chain.Client, - ) - return deployment.ContractDeploy[*weth9.WETH9]{ - weth9Addr, weth9c, tx2, deployment.NewTypeAndVersion(WETH9, deployment.Version1_0_0), err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy weth9", "err", err) - return err - } - lggr.Infow("deployed weth9", "addr", weth.Address) - weth9Contract = weth.Contract - } else { - lggr.Infow("weth9 already deployed", "addr", weth9Contract.Address) - } - if linkTokenContract == nil { - linkToken, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { - linkTokenAddr, tx2, linkToken, err2 := burn_mint_erc677.DeployBurnMintERC677( - chain.DeployerKey, - chain.Client, - "Link Token", - "LINK", - uint8(18), - big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), - ) - return deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ - linkTokenAddr, linkToken, tx2, deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0), err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy linkToken", "err", err) - return err - } - lggr.Infow("deployed linkToken", "addr", linkToken.Address) - } else { - lggr.Infow("linkToken already deployed", "addr", linkTokenContract.Address) - } - // if router is not already deployed, we deploy it - if r == nil { - routerContract, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*router.Router] { - routerAddr, tx2, routerC, err2 := router.DeployRouter( - chain.DeployerKey, - chain.Client, - weth9Contract.Address(), - rmnProxy.Address(), - ) - return deployment.ContractDeploy[*router.Router]{ - routerAddr, routerC, tx2, deployment.NewTypeAndVersion(Router, deployment.Version1_2_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy router", "err", err) - return err - } - e.Logger.Infow("deployed router", "addr", routerContract.Address) - r = routerContract.Contract - } else { - e.Logger.Infow("router already deployed", "addr", chainState.Router.Address) - } - if deployOpts.Multicall3Enabled && mc3 == nil { - multicall3Contract, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*multicall3.Multicall3] { - multicall3Addr, tx2, multicall3Wrapper, err2 := multicall3.DeployMulticall3( - chain.DeployerKey, - chain.Client, - ) - return deployment.ContractDeploy[*multicall3.Multicall3]{ - multicall3Addr, multicall3Wrapper, tx2, deployment.NewTypeAndVersion(Multicall3, deployment.Version1_0_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy ccip multicall", "err", err) - return err - } - e.Logger.Infow("deployed ccip multicall", "addr", multicall3Contract.Address) - } else { - e.Logger.Info("ccip multicall already deployed", "addr", mc3.Address) - } - if isUSDC { - token, pool, messenger, transmitter, err1 := DeployUSDC(e.Logger, chain, ab, rmnProxy.Address(), r.Address()) - if err1 != nil { - return err1 - } - e.Logger.Infow("Deployed USDC contracts", - "chainSelector", chain.Selector, - "token", token.Address(), - "pool", pool.Address(), - "transmitter", transmitter.Address(), - "messenger", messenger.Address(), - ) - } - return nil -} - -// configureChain assumes the all the Home chain contracts and CCIP contracts are deployed -// It does - -// 1. AddChainConfig for each chain in CCIPHome -// 2. Registers the nodes with the capability registry -// 3. SetOCR3Config on the remote chain -func configureChain( - e deployment.Environment, - c NewChainsConfig, -) error { - if c.OCRSecrets.IsEmpty() { - return fmt.Errorf("OCR secrets are empty") - } - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - if err != nil || len(nodes) == 0 { - e.Logger.Errorw("Failed to get node info", "err", err) - return err - } - existingState, err := LoadOnchainState(e) - if err != nil { - e.Logger.Errorw("Failed to load existing onchain state", "err") - return err - } - capReg := existingState.Chains[c.HomeChainSel].CapabilityRegistry - if capReg == nil { - e.Logger.Errorw("Failed to get capability registry") - return fmt.Errorf("capability registry not found") - } - ccipHome := existingState.Chains[c.HomeChainSel].CCIPHome - if ccipHome == nil { - e.Logger.Errorw("Failed to get ccip home", "err", err) - return fmt.Errorf("ccip home not found") - } - rmnHome := existingState.Chains[c.HomeChainSel].RMNHome - if rmnHome == nil { - e.Logger.Errorw("Failed to get rmn home", "err", err) - return fmt.Errorf("rmn home not found") - } - - for _, chainSel := range c.ChainsToDeploy { - chain, _ := e.Chains[chainSel] - chainState, ok := existingState.Chains[chain.Selector] - if !ok { - return fmt.Errorf("chain state not found for chain %d", chain.Selector) - } - ocrParams, ok := c.OCRParams[chain.Selector] - if !ok { - return fmt.Errorf("OCR params not found for chain %d", chain.Selector) - } - if chainState.OffRamp == nil { - return fmt.Errorf("off ramp not found for chain %d", chain.Selector) - } - _, err = AddChainConfig( - e.Logger, - e.Chains[c.HomeChainSel], - ccipHome, - chain.Selector, - nodes.NonBootstraps().PeerIDs()) - if err != nil { - return err - } - if enabled, ok := c.USDCConfig.EnabledChainMap()[chainSel]; ok && enabled { - ocrParams.ExecuteOffChainConfig.TokenDataObservers = c.USDCConfig.ToTokenDataObserverConfig() - } - ocrParams.CommitOffChainConfig.PriceFeedChainSelector = cciptypes.ChainSelector(c.FeedChainSel) - // For each chain, we create a DON on the home chain (2 OCR instances) - if err := addDON( - e.Logger, - c.OCRSecrets, - capReg, - ccipHome, - rmnHome.Address(), - chainState.OffRamp, - chain, - e.Chains[c.HomeChainSel], - nodes.NonBootstraps(), - ocrParams, - ); err != nil { - e.Logger.Errorw("Failed to add DON", "err", err) - return err - } - } - - return nil -} - -// deployCCIPContracts assumes the following contracts are deployed: -// - Capability registry -// - CCIP home -// - RMN home -// - Fee tokens on all chains. -// and present in ExistingAddressBook. -// It then deploys the rest of the CCIP chain contracts to the selected chains -// registers the nodes with the capability registry and creates a DON for -// each new chain. -func deployCCIPContracts( - e deployment.Environment, - ab deployment.AddressBook, - c NewChainsConfig) error { - err := deployChainContractsForChains(e, ab, c.HomeChainSel, c.ChainsToDeploy) - if err != nil { - e.Logger.Errorw("Failed to deploy chain contracts", "err", err) - return err - } - err = e.ExistingAddresses.Merge(ab) - if err != nil { - e.Logger.Errorw("Failed to merge address book", "err", err) - return err - } - state, err := LoadOnchainState(e) - if err != nil { - e.Logger.Errorw("Failed to load existing onchain state", "err", err) - return err - } - - ocrParams := make(map[uint64]CCIPOCRParams) - for _, chain := range c.ChainsToDeploy { - tokenInfo := c.TokenConfig.GetTokenInfo(e.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9) - ocrParams[chain] = DefaultOCRParams(c.FeedChainSel, tokenInfo) - } - c.OCRParams = ocrParams - err = configureChain(e, c) - if err != nil { - e.Logger.Errorw("Failed to add chain", "err", err) - return err - } - - return nil -} - -func deployChainContractsForChains( - e deployment.Environment, - ab deployment.AddressBook, - homeChainSel uint64, - chainsToDeploy []uint64) error { - existingState, err := LoadOnchainState(e) - if err != nil { - e.Logger.Errorw("Failed to load existing onchain state", "err") - return err - } - - capReg := existingState.Chains[homeChainSel].CapabilityRegistry - if capReg == nil { - e.Logger.Errorw("Failed to get capability registry") - return fmt.Errorf("capability registry not found") - } - cr, err := capReg.GetHashedCapabilityId( - &bind.CallOpts{}, internal.CapabilityLabelledName, internal.CapabilityVersion) - if err != nil { - e.Logger.Errorw("Failed to get hashed capability id", "err", err) - return err - } - if cr != internal.CCIPCapabilityID { - return fmt.Errorf("unexpected mismatch between calculated ccip capability id (%s) and expected ccip capability id constant (%s)", - hexutil.Encode(cr[:]), - hexutil.Encode(internal.CCIPCapabilityID[:])) - } - capability, err := capReg.GetCapability(nil, internal.CCIPCapabilityID) - if err != nil { - e.Logger.Errorw("Failed to get capability", "err", err) - return err - } - ccipHome, err := ccip_home.NewCCIPHome(capability.ConfigurationContract, e.Chains[homeChainSel].Client) - if err != nil { - e.Logger.Errorw("Failed to get ccip config", "err", err) - return err - } - if ccipHome.Address() != existingState.Chains[homeChainSel].CCIPHome.Address() { - return fmt.Errorf("ccip home address mismatch") - } - rmnHome := existingState.Chains[homeChainSel].RMNHome - if rmnHome == nil { - e.Logger.Errorw("Failed to get rmn home", "err", err) - return fmt.Errorf("rmn home not found") - } - deployGrp := errgroup.Group{} - for _, chainSel := range chainsToDeploy { - chain, ok := e.Chains[chainSel] - if !ok { - return fmt.Errorf("chain %d not found", chainSel) - } - if existingState.Chains[chainSel].LinkToken == nil || existingState.Chains[chainSel].Weth9 == nil { - return fmt.Errorf("fee tokens not found for chain %d", chainSel) - } - deployGrp.Go( - func() error { - err := deployChainContracts(e, chain, ab, rmnHome) - if err != nil { - e.Logger.Errorw("Failed to deploy chain contracts", "chain", chainSel, "err", err) - return fmt.Errorf("failed to deploy chain contracts for chain %d: %w", chainSel, err) - } - return nil - }) - } - if err := deployGrp.Wait(); err != nil { - e.Logger.Errorw("Failed to deploy chain contracts", "err", err) - return err - } - return nil -} - -func deployChainContracts( - e deployment.Environment, - chain deployment.Chain, - ab deployment.AddressBook, - rmnHome *rmn_home.RMNHome, -) error { - // check for existing contracts - state, err := LoadOnchainState(e) - if err != nil { - e.Logger.Errorw("Failed to load existing onchain state", "err") - return err - } - chainState, chainExists := state.Chains[chain.Selector] - if !chainExists { - return fmt.Errorf("chain %d not found in existing state, deploy the prerequisites first", chain.Selector) - } - if chainState.Weth9 == nil { - return fmt.Errorf("weth9 not found for chain %d, deploy the prerequisites first", chain.Selector) - } - if chainState.Timelock == nil { - return fmt.Errorf("timelock not found for chain %d, deploy the mcms contracts first", chain.Selector) - } - weth9Contract := chainState.Weth9 - if chainState.LinkToken == nil { - return fmt.Errorf("link token not found for chain %d, deploy the prerequisites first", chain.Selector) - } - linkTokenContract := chainState.LinkToken - if chainState.TokenAdminRegistry == nil { - return fmt.Errorf("token admin registry not found for chain %d, deploy the prerequisites first", chain.Selector) - } - tokenAdminReg := chainState.TokenAdminRegistry - if chainState.RegistryModule == nil { - return fmt.Errorf("registry module not found for chain %d, deploy the prerequisites first", chain.Selector) - } - if chainState.Router == nil { - return fmt.Errorf("router not found for chain %d, deploy the prerequisites first", chain.Selector) - } - if chainState.Receiver == nil { - ccipReceiver, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver] { - receiverAddr, tx, receiver, err2 := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver( - chain.DeployerKey, - chain.Client, - false, - ) - return deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver]{ - receiverAddr, receiver, tx, deployment.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy receiver", "err", err) - return err - } - e.Logger.Infow("deployed receiver", "addr", ccipReceiver.Address) - } else { - e.Logger.Infow("receiver already deployed", "addr", chainState.Receiver.Address) - } - rmnRemoteContract := chainState.RMNRemote - if chainState.RMNRemote == nil { - // TODO: Correctly configure RMN remote. - rmnRemote, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*rmn_remote.RMNRemote] { - rmnRemoteAddr, tx, rmnRemote, err2 := rmn_remote.DeployRMNRemote( - chain.DeployerKey, - chain.Client, - chain.Selector, - ) - return deployment.ContractDeploy[*rmn_remote.RMNRemote]{ - rmnRemoteAddr, rmnRemote, tx, deployment.NewTypeAndVersion(RMNRemote, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy RMNRemote", "err", err) - return err - } - e.Logger.Infow("deployed RMNRemote", "addr", rmnRemote.Address) - rmnRemoteContract = rmnRemote.Contract - } else { - e.Logger.Infow("rmn remote already deployed", "addr", chainState.RMNRemote.Address) - } - activeDigest, err := rmnHome.GetActiveDigest(&bind.CallOpts{}) - if err != nil { - e.Logger.Errorw("Failed to get active digest", "err", err) - return err - } - e.Logger.Infow("setting active home digest to rmn remote", "digest", activeDigest) - - tx, err := rmnRemoteContract.SetConfig(chain.DeployerKey, rmn_remote.RMNRemoteConfig{ - RmnHomeContractConfigDigest: activeDigest, - Signers: []rmn_remote.RMNRemoteSigner{ - {NodeIndex: 0, OnchainPublicKey: common.Address{1}}, - }, - F: 0, // TODO: update when we have signers - }) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - e.Logger.Errorw("Failed to confirm RMNRemote config", "err", err) - return err - } - - // we deploy a new RMNProxy so that RMNRemote can be tested first before pointing it to the main Existing RMNProxy - // To differentiate between the two RMNProxies, we will deploy new one with Version1_6_0_dev - rmnProxyContract := chainState.RMNProxyNew - if chainState.RMNProxyNew == nil { - // we deploy a new rmnproxy contract to test RMNRemote - rmnProxy, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract] { - rmnProxyAddr, tx, rmnProxy, err2 := rmn_proxy_contract.DeployRMNProxyContract( - chain.DeployerKey, - chain.Client, - rmnRemoteContract.Address(), - ) - return deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract]{ - rmnProxyAddr, rmnProxy, tx, deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy RMNProxyNew", "err", err) - return err - } - e.Logger.Infow("deployed new RMNProxyNew", "addr", rmnProxy.Address) - rmnProxyContract = rmnProxy.Contract - } else { - e.Logger.Infow("rmn proxy already deployed", "addr", chainState.RMNProxyNew.Address) - } - if chainState.TestRouter == nil { - testRouterContract, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*router.Router] { - routerAddr, tx2, routerC, err2 := router.DeployRouter( - chain.DeployerKey, - chain.Client, - weth9Contract.Address(), - rmnProxyContract.Address(), - ) - return deployment.ContractDeploy[*router.Router]{ - routerAddr, routerC, tx2, deployment.NewTypeAndVersion(TestRouter, deployment.Version1_2_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy test router", "err", err) - return err - } - e.Logger.Infow("deployed test router", "addr", testRouterContract.Address) - } else { - e.Logger.Infow("test router already deployed", "addr", chainState.TestRouter.Address) - } - - nmContract := chainState.NonceManager - if chainState.NonceManager == nil { - nonceManager, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*nonce_manager.NonceManager] { - nonceManagerAddr, tx2, nonceManager, err2 := nonce_manager.DeployNonceManager( - chain.DeployerKey, - chain.Client, - []common.Address{}, // Need to add onRamp after - ) - return deployment.ContractDeploy[*nonce_manager.NonceManager]{ - nonceManagerAddr, nonceManager, tx2, deployment.NewTypeAndVersion(NonceManager, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy nonce manager", "err", err) - return err - } - e.Logger.Infow("Deployed nonce manager", "addr", nonceManager.Address) - nmContract = nonceManager.Contract - } else { - e.Logger.Infow("nonce manager already deployed", "addr", chainState.NonceManager.Address) - } - feeQuoterContract := chainState.FeeQuoter - if chainState.FeeQuoter == nil { - feeQuoter, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*fee_quoter.FeeQuoter] { - prAddr, tx2, pr, err2 := fee_quoter.DeployFeeQuoter( - chain.DeployerKey, - chain.Client, - fee_quoter.FeeQuoterStaticConfig{ - MaxFeeJuelsPerMsg: big.NewInt(0).Mul(big.NewInt(2e2), big.NewInt(1e18)), - LinkToken: linkTokenContract.Address(), - TokenPriceStalenessThreshold: uint32(24 * 60 * 60), - }, - []common.Address{state.Chains[chain.Selector].Timelock.Address()}, // timelock should be able to update, ramps added after - []common.Address{weth9Contract.Address(), linkTokenContract.Address()}, // fee tokens - []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, - []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, // TODO: tokens - []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{ - { - PremiumMultiplierWeiPerEth: 9e17, // 0.9 ETH - Token: linkTokenContract.Address(), - }, - { - PremiumMultiplierWeiPerEth: 1e18, - Token: weth9Contract.Address(), - }, - }, - []fee_quoter.FeeQuoterDestChainConfigArgs{}, - ) - return deployment.ContractDeploy[*fee_quoter.FeeQuoter]{ - prAddr, pr, tx2, deployment.NewTypeAndVersion(FeeQuoter, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy fee quoter", "err", err) - return err - } - e.Logger.Infow("Deployed fee quoter", "addr", feeQuoter.Address) - feeQuoterContract = feeQuoter.Contract - } else { - e.Logger.Infow("fee quoter already deployed", "addr", chainState.FeeQuoter.Address) - } - onRampContract := chainState.OnRamp - if onRampContract == nil { - onRamp, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*onramp.OnRamp] { - onRampAddr, tx2, onRamp, err2 := onramp.DeployOnRamp( - chain.DeployerKey, - chain.Client, - onramp.OnRampStaticConfig{ - ChainSelector: chain.Selector, - RmnRemote: rmnProxyContract.Address(), - NonceManager: nmContract.Address(), - TokenAdminRegistry: tokenAdminReg.Address(), - }, - onramp.OnRampDynamicConfig{ - FeeQuoter: feeQuoterContract.Address(), - FeeAggregator: common.HexToAddress("0x1"), // TODO real fee aggregator - }, - []onramp.OnRampDestChainConfigArgs{}, - ) - return deployment.ContractDeploy[*onramp.OnRamp]{ - onRampAddr, onRamp, tx2, deployment.NewTypeAndVersion(OnRamp, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy onramp", "err", err) - return err - } - e.Logger.Infow("Deployed onramp", "addr", onRamp.Address) - onRampContract = onRamp.Contract - } else { - e.Logger.Infow("onramp already deployed", "addr", chainState.OnRamp.Address) - } - offRampContract := chainState.OffRamp - if offRampContract == nil { - offRamp, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*offramp.OffRamp] { - offRampAddr, tx2, offRamp, err2 := offramp.DeployOffRamp( - chain.DeployerKey, - chain.Client, - offramp.OffRampStaticConfig{ - ChainSelector: chain.Selector, - RmnRemote: rmnProxyContract.Address(), - NonceManager: nmContract.Address(), - TokenAdminRegistry: tokenAdminReg.Address(), - }, - offramp.OffRampDynamicConfig{ - FeeQuoter: feeQuoterContract.Address(), - PermissionLessExecutionThresholdSeconds: uint32(86400), - IsRMNVerificationDisabled: true, - }, - []offramp.OffRampSourceChainConfigArgs{}, - ) - return deployment.ContractDeploy[*offramp.OffRamp]{ - Address: offRampAddr, Contract: offRamp, Tx: tx2, Tv: deployment.NewTypeAndVersion(OffRamp, deployment.Version1_6_0_dev), Err: err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy offramp", "err", err) - return err - } - e.Logger.Infow("Deployed offramp", "addr", offRamp.Address) - offRampContract = offRamp.Contract - } else { - e.Logger.Infow("offramp already deployed", "addr", chainState.OffRamp.Address) - } - // Basic wiring is always needed. - tx, err = feeQuoterContract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, fee_quoter.AuthorizedCallersAuthorizedCallerArgs{ - // TODO: We enable the deployer initially to set prices - // Should be removed after. - AddedCallers: []common.Address{offRampContract.Address(), chain.DeployerKey.From}, - }) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - e.Logger.Errorw("Failed to confirm fee quoter authorized caller update", "err", err) - return err - } - - tx, err = nmContract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, nonce_manager.AuthorizedCallersAuthorizedCallerArgs{ - AddedCallers: []common.Address{offRampContract.Address(), onRampContract.Address()}, - }) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - e.Logger.Errorw("Failed to update nonce manager with ramps", "err", err) - return err - } - return nil -} diff --git a/deployment/ccip/changeset/deploy_chain.go b/deployment/ccip/changeset/deploy_chain.go deleted file mode 100644 index d0f44724070..00000000000 --- a/deployment/ccip/changeset/deploy_chain.go +++ /dev/null @@ -1,50 +0,0 @@ -package changeset - -import ( - "fmt" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" -) - -var _ deployment.ChangeSet[DeployChainContractsConfig] = DeployChainContracts - -// DeployChainContracts deploys all new CCIP v1.6 or later contracts for the given chains. -// It returns the new addresses for the contracts. -// DeployChainContracts is idempotent. If there is an error, it will return the successfully deployed addresses and the error so that the caller can call the -// changeset again with the same input to retry the failed deployment. -// Caller should update the environment's address book with the returned addresses. -func DeployChainContracts(env deployment.Environment, c DeployChainContractsConfig) (deployment.ChangesetOutput, error) { - if err := c.Validate(); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("invalid DeployChainContractsConfig: %w", err) - } - newAddresses := deployment.NewMemoryAddressBook() - err := deployChainContractsForChains(env, newAddresses, c.HomeChainSelector, c.ChainSelectors) - if err != nil { - env.Logger.Errorw("Failed to deploy CCIP contracts", "err", err, "newAddresses", newAddresses) - return deployment.ChangesetOutput{AddressBook: newAddresses}, deployment.MaybeDataErr(err) - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{}, - AddressBook: newAddresses, - JobSpecs: nil, - }, nil -} - -type DeployChainContractsConfig struct { - ChainSelectors []uint64 - HomeChainSelector uint64 -} - -func (c DeployChainContractsConfig) Validate() error { - for _, cs := range c.ChainSelectors { - if err := deployment.IsValidChainSelector(cs); err != nil { - return fmt.Errorf("invalid chain selector: %d - %w", cs, err) - } - } - if err := deployment.IsValidChainSelector(c.HomeChainSelector); err != nil { - return fmt.Errorf("invalid home chain selector: %d - %w", c.HomeChainSelector, err) - } - return nil -} diff --git a/deployment/ccip/changeset/deploy_home_chain.go b/deployment/ccip/changeset/deploy_home_chain.go deleted file mode 100644 index 881f7c386c3..00000000000 --- a/deployment/ccip/changeset/deploy_home_chain.go +++ /dev/null @@ -1,561 +0,0 @@ -package changeset - -import ( - "bytes" - "context" - "encoding/hex" - "encoding/json" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink-ccip/chainconfig" - "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" -) - -// DeployCapReg deploys the CapabilitiesRegistry contract if it is not already deployed -// and returns a deployment.ContractDeploy struct with the address and contract instance. -func DeployCapReg( - lggr logger.Logger, - state CCIPOnChainState, - ab deployment.AddressBook, - chain deployment.Chain, -) (*deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { - homeChainState, exists := state.Chains[chain.Selector] - if exists { - cr := homeChainState.CapabilityRegistry - if cr != nil { - lggr.Infow("Found CapabilitiesRegistry in chain state", "address", cr.Address().String()) - return &deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ - Address: cr.Address(), Contract: cr, Tv: deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0), - }, nil - } - } - capReg, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { - crAddr, tx, cr, err2 := capabilities_registry.DeployCapabilitiesRegistry( - chain.DeployerKey, - chain.Client, - ) - return deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ - Address: crAddr, Contract: cr, Tv: deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0), Tx: tx, Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy capreg", "err", err) - return nil, err - } - return capReg, nil -} - -func deployHomeChain( - lggr logger.Logger, - e deployment.Environment, - ab deployment.AddressBook, - chain deployment.Chain, - rmnHomeStatic rmn_home.RMNHomeStaticConfig, - rmnHomeDynamic rmn_home.RMNHomeDynamicConfig, - nodeOps []capabilities_registry.CapabilitiesRegistryNodeOperator, - nodeP2PIDsPerNodeOpAdmin map[string][][32]byte, -) (*deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { - // load existing state - state, err := LoadOnchainState(e) - if err != nil { - return nil, fmt.Errorf("failed to load onchain state: %w", err) - } - // Deploy CapabilitiesRegistry, CCIPHome, RMNHome - capReg, err := DeployCapReg(lggr, state, ab, chain) - if err != nil { - return nil, err - } - - lggr.Infow("deployed/connected to capreg", "addr", capReg.Address) - ccipHome, err := deployment.DeployContract( - lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*ccip_home.CCIPHome] { - ccAddr, tx, cc, err2 := ccip_home.DeployCCIPHome( - chain.DeployerKey, - chain.Client, - capReg.Address, - ) - return deployment.ContractDeploy[*ccip_home.CCIPHome]{ - Address: ccAddr, Tv: deployment.NewTypeAndVersion(CCIPHome, deployment.Version1_6_0_dev), Tx: tx, Err: err2, Contract: cc, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy CCIPHome", "err", err) - return nil, err - } - lggr.Infow("deployed CCIPHome", "addr", ccipHome.Address) - - rmnHome, err := deployment.DeployContract( - lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*rmn_home.RMNHome] { - rmnAddr, tx, rmn, err2 := rmn_home.DeployRMNHome( - chain.DeployerKey, - chain.Client, - ) - return deployment.ContractDeploy[*rmn_home.RMNHome]{ - Address: rmnAddr, Tv: deployment.NewTypeAndVersion(RMNHome, deployment.Version1_6_0_dev), Tx: tx, Err: err2, Contract: rmn, - } - }, - ) - if err != nil { - lggr.Errorw("Failed to deploy RMNHome", "err", err) - return nil, err - } - lggr.Infow("deployed RMNHome", "addr", rmnHome.Address) - - // considering the RMNHome is recently deployed, there is no digest to overwrite - tx, err := rmnHome.Contract.SetCandidate(chain.DeployerKey, rmnHomeStatic, rmnHomeDynamic, [32]byte{}) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to set candidate on RMNHome", "err", err) - return nil, err - } - - rmnCandidateDigest, err := rmnHome.Contract.GetCandidateDigest(nil) - if err != nil { - lggr.Errorw("Failed to get RMNHome candidate digest", "err", err) - return nil, err - } - - tx, err = rmnHome.Contract.PromoteCandidateAndRevokeActive(chain.DeployerKey, rmnCandidateDigest, [32]byte{}) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to promote candidate and revoke active on RMNHome", "err", err) - return nil, err - } - - rmnActiveDigest, err := rmnHome.Contract.GetActiveDigest(nil) - if err != nil { - lggr.Errorw("Failed to get RMNHome active digest", "err", err) - return nil, err - } - lggr.Infow("Got rmn home active digest", "digest", rmnActiveDigest) - - if rmnActiveDigest != rmnCandidateDigest { - lggr.Errorw("RMNHome active digest does not match previously candidate digest", - "active", rmnActiveDigest, "candidate", rmnCandidateDigest) - return nil, errors.New("RMNHome active digest does not match candidate digest") - } - - tx, err = capReg.Contract.AddCapabilities(chain.DeployerKey, []capabilities_registry.CapabilitiesRegistryCapability{ - { - LabelledName: internal.CapabilityLabelledName, - Version: internal.CapabilityVersion, - CapabilityType: 2, // consensus. not used (?) - ResponseType: 0, // report. not used (?) - ConfigurationContract: ccipHome.Address, - }, - }) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to add capabilities", "err", err) - return nil, err - } - - tx, err = capReg.Contract.AddNodeOperators(chain.DeployerKey, nodeOps) - txBlockNum, err := deployment.ConfirmIfNoError(chain, tx, err) - if err != nil { - lggr.Errorw("Failed to add node operators", "err", err) - return nil, err - } - addedEvent, err := capReg.Contract.FilterNodeOperatorAdded(&bind.FilterOpts{ - Start: txBlockNum, - Context: context.Background(), - }, nil, nil) - if err != nil { - lggr.Errorw("Failed to filter NodeOperatorAdded event", "err", err) - return capReg, err - } - // Need to fetch nodeoperators ids to be able to add nodes for corresponding node operators - p2pIDsByNodeOpId := make(map[uint32][][32]byte) - for addedEvent.Next() { - for nopName, p2pId := range nodeP2PIDsPerNodeOpAdmin { - if addedEvent.Event.Name == nopName { - lggr.Infow("Added node operator", "admin", addedEvent.Event.Admin, "name", addedEvent.Event.Name) - p2pIDsByNodeOpId[addedEvent.Event.NodeOperatorId] = p2pId - } - } - } - if len(p2pIDsByNodeOpId) != len(nodeP2PIDsPerNodeOpAdmin) { - lggr.Errorw("Failed to add all node operators", "added", maps.Keys(p2pIDsByNodeOpId), "expected", maps.Keys(nodeP2PIDsPerNodeOpAdmin)) - return capReg, errors.New("failed to add all node operators") - } - // Adds initial set of nodes to CR, who all have the CCIP capability - if err := AddNodes(lggr, capReg.Contract, chain, p2pIDsByNodeOpId); err != nil { - return capReg, err - } - return capReg, nil -} - -func isEqualCapabilitiesRegistryNodeParams(a, b capabilities_registry.CapabilitiesRegistryNodeParams) (bool, error) { - aBytes, err := json.Marshal(a) - if err != nil { - return false, err - } - bBytes, err := json.Marshal(b) - if err != nil { - return false, err - } - return bytes.Equal(aBytes, bBytes), nil -} - -func AddNodes( - lggr logger.Logger, - capReg *capabilities_registry.CapabilitiesRegistry, - chain deployment.Chain, - p2pIDsByNodeOpId map[uint32][][32]byte, -) error { - var nodeParams []capabilities_registry.CapabilitiesRegistryNodeParams - nodes, err := capReg.GetNodes(nil) - if err != nil { - return err - } - existingNodeParams := make(map[p2ptypes.PeerID]capabilities_registry.CapabilitiesRegistryNodeParams) - for _, node := range nodes { - existingNodeParams[node.P2pId] = capabilities_registry.CapabilitiesRegistryNodeParams{ - NodeOperatorId: node.NodeOperatorId, - Signer: node.Signer, - P2pId: node.P2pId, - HashedCapabilityIds: node.HashedCapabilityIds, - } - } - for nopID, p2pIDs := range p2pIDsByNodeOpId { - for _, p2pID := range p2pIDs { - // if any p2pIDs are empty throw error - if bytes.Equal(p2pID[:], make([]byte, 32)) { - return errors.Wrapf(errors.New("empty p2pID"), "p2pID: %x selector: %d", p2pID, chain.Selector) - } - nodeParam := capabilities_registry.CapabilitiesRegistryNodeParams{ - NodeOperatorId: nopID, - Signer: p2pID, // Not used in tests - P2pId: p2pID, - EncryptionPublicKey: p2pID, // Not used in tests - HashedCapabilityIds: [][32]byte{internal.CCIPCapabilityID}, - } - if existing, ok := existingNodeParams[p2pID]; ok { - if isEqual, err := isEqualCapabilitiesRegistryNodeParams(existing, nodeParam); err != nil && isEqual { - lggr.Infow("Node already exists", "p2pID", p2pID) - continue - } - } - - nodeParams = append(nodeParams, nodeParam) - } - } - if len(nodeParams) == 0 { - lggr.Infow("No new nodes to add") - return nil - } - tx, err := capReg.AddNodes(chain.DeployerKey, nodeParams) - if err != nil { - lggr.Errorw("Failed to add nodes", "err", deployment.MaybeDataErr(err)) - return err - } - _, err = chain.Confirm(tx) - return err -} - -func SetupConfigInfo(chainSelector uint64, readers [][32]byte, fChain uint8, cfg []byte) ccip_home.CCIPHomeChainConfigArgs { - return ccip_home.CCIPHomeChainConfigArgs{ - ChainSelector: chainSelector, - ChainConfig: ccip_home.CCIPHomeChainConfig{ - Readers: readers, - FChain: fChain, - Config: cfg, - }, - } -} - -func AddChainConfig( - lggr logger.Logger, - h deployment.Chain, - ccipConfig *ccip_home.CCIPHome, - chainSelector uint64, - p2pIDs [][32]byte, -) (ccip_home.CCIPHomeChainConfigArgs, error) { - // First Add ChainConfig that includes all p2pIDs as readers - encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ - GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), - DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), - OptimisticConfirmations: 1, - }) - if err != nil { - return ccip_home.CCIPHomeChainConfigArgs{}, err - } - chainConfig := SetupConfigInfo(chainSelector, p2pIDs, uint8(len(p2pIDs)/3), encodedExtraChainConfig) - tx, err := ccipConfig.ApplyChainConfigUpdates(h.DeployerKey, nil, []ccip_home.CCIPHomeChainConfigArgs{ - chainConfig, - }) - if _, err := deployment.ConfirmIfNoError(h, tx, err); err != nil { - return ccip_home.CCIPHomeChainConfigArgs{}, err - } - lggr.Infow("Applied chain config updates", "chainConfig", chainConfig) - return chainConfig, nil -} - -// CreateDON creates one DON with 2 plugins (commit and exec) -// It first set a new candidate for the DON with the first plugin type and AddDON on capReg -// Then for subsequent operations it uses UpdateDON to promote the first plugin to the active deployment -// and to set candidate and promote it for the second plugin -func CreateDON( - lggr logger.Logger, - capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, - ocr3Configs map[cctypes.PluginType]ccip_home.CCIPHomeOCR3Config, - home deployment.Chain, - newChainSel uint64, - nodes deployment.Nodes, -) error { - commitConfig, ok := ocr3Configs[cctypes.PluginTypeCCIPCommit] - if !ok { - return fmt.Errorf("missing commit plugin in ocr3Configs") - } - - execConfig, ok := ocr3Configs[cctypes.PluginTypeCCIPExec] - if !ok { - return fmt.Errorf("missing exec plugin in ocr3Configs") - } - - latestDon, err := internal.LatestCCIPDON(capReg) - if err != nil { - return err - } - - donID := latestDon.Id + 1 - - err = internal.SetupCommitDON(donID, commitConfig, capReg, home, nodes, ccipHome) - if err != nil { - return fmt.Errorf("setup commit don: %w", err) - } - - // TODO: bug in contract causing this to not work as expected. - err = internal.SetupExecDON(donID, execConfig, capReg, home, nodes, ccipHome) - if err != nil { - return fmt.Errorf("setup exec don: %w", err) - } - return ValidateCCIPHomeConfigSetUp(capReg, ccipHome, newChainSel) -} - -// SetCandidateCommitPluginWithAddDonOps sets the candidate commit config by calling setCandidate on CCIPHome contract through the AddDON call on CapReg contract -// This should be done first before calling any other UpdateDON calls -// This proposes to set up OCR3 config for the commit plugin for the DON -func NewDonWithCandidateOp( - donID uint32, - pluginConfig ccip_home.CCIPHomeOCR3Config, - capReg *capabilities_registry.CapabilitiesRegistry, - nodes deployment.Nodes, -) (mcms.Operation, error) { - encodedSetCandidateCall, err := internal.CCIPHomeABI.Pack( - "setCandidate", - donID, - pluginConfig.PluginType, - pluginConfig, - [32]byte{}, - ) - if err != nil { - return mcms.Operation{}, fmt.Errorf("pack set candidate call: %w", err) - } - addDonTx, err := capReg.AddDON(deployment.SimTransactOpts(), nodes.PeerIDs(), []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: internal.CCIPCapabilityID, - Config: encodedSetCandidateCall, - }, - }, false, false, nodes.DefaultF()) - if err != nil { - return mcms.Operation{}, fmt.Errorf("could not generate add don tx w/ commit config: %w", err) - } - return mcms.Operation{ - To: capReg.Address(), - Data: addDonTx.Data(), - Value: big.NewInt(0), - }, nil -} - -// ValidateCCIPHomeConfigSetUp checks that the commit and exec active and candidate configs are set up correctly -func ValidateCCIPHomeConfigSetUp( - capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, - chainSel uint64, -) error { - // fetch DONID - donID, err := internal.DonIDForChain(capReg, ccipHome, chainSel) - if err != nil { - return fmt.Errorf("fetch don id for chain: %w", err) - } - // final sanity checks on configs. - commitConfigs, err := ccipHome.GetAllConfigs(&bind.CallOpts{ - //Pending: true, - }, donID, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("get all commit configs: %w", err) - } - commitActiveDigest, err := ccipHome.GetActiveDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("get active commit digest: %w", err) - } - commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("get commit candidate digest: %w", err) - } - if commitConfigs.ActiveConfig.ConfigDigest == [32]byte{} { - return fmt.Errorf( - "active config digest is empty for commit, expected nonempty, donID: %d, cfg: %+v, config digest from GetActiveDigest call: %x, config digest from GetCandidateDigest call: %x", - donID, commitConfigs.ActiveConfig, commitActiveDigest, commitCandidateDigest) - } - if commitConfigs.CandidateConfig.ConfigDigest != [32]byte{} { - return fmt.Errorf( - "candidate config digest is nonempty for commit, expected empty, donID: %d, cfg: %+v, config digest from GetCandidateDigest call: %x, config digest from GetActiveDigest call: %x", - donID, commitConfigs.CandidateConfig, commitCandidateDigest, commitActiveDigest) - } - - execConfigs, err := ccipHome.GetAllConfigs(nil, donID, uint8(cctypes.PluginTypeCCIPExec)) - if err != nil { - return fmt.Errorf("get all exec configs: %w", err) - } - if execConfigs.ActiveConfig.ConfigDigest == [32]byte{} { - return fmt.Errorf("active config digest is empty for exec, expected nonempty, cfg: %v", execConfigs.ActiveConfig) - } - if execConfigs.CandidateConfig.ConfigDigest != [32]byte{} { - return fmt.Errorf("candidate config digest is nonempty for exec, expected empty, cfg: %v", execConfigs.CandidateConfig) - } - return nil -} - -func addDON( - lggr logger.Logger, - ocrSecrets deployment.OCRSecrets, - capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, - rmnHomeAddress common.Address, - offRamp *offramp.OffRamp, - dest deployment.Chain, - home deployment.Chain, - nodes deployment.Nodes, - ocrParams CCIPOCRParams, -) error { - ocrConfigs, err := internal.BuildOCR3ConfigForCCIPHome( - ocrSecrets, offRamp, dest, nodes, rmnHomeAddress, ocrParams.OCRParameters, ocrParams.CommitOffChainConfig, ocrParams.ExecuteOffChainConfig) - if err != nil { - return err - } - err = CreateDON(lggr, capReg, ccipHome, ocrConfigs, home, dest.Selector, nodes) - if err != nil { - return err - } - don, err := internal.LatestCCIPDON(capReg) - if err != nil { - return err - } - lggr.Infow("Added DON", "donID", don.Id) - - offrampOCR3Configs, err := internal.BuildSetOCR3ConfigArgs(don.Id, ccipHome, dest.Selector) - if err != nil { - return err - } - lggr.Infow("Setting OCR3 Configs", - "offrampOCR3Configs", offrampOCR3Configs, - "configDigestCommit", hex.EncodeToString(offrampOCR3Configs[cctypes.PluginTypeCCIPCommit].ConfigDigest[:]), - "configDigestExec", hex.EncodeToString(offrampOCR3Configs[cctypes.PluginTypeCCIPExec].ConfigDigest[:]), - "chainSelector", dest.Selector, - ) - - tx, err := offRamp.SetOCR3Configs(dest.DeployerKey, offrampOCR3Configs) - if _, err := deployment.ConfirmIfNoError(dest, tx, err); err != nil { - return err - } - - mapOfframpOCR3Configs := make(map[cctypes.PluginType]offramp.MultiOCR3BaseOCRConfigArgs) - for _, config := range offrampOCR3Configs { - mapOfframpOCR3Configs[cctypes.PluginType(config.OcrPluginType)] = config - } - - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - ocrConfig, err := offRamp.LatestConfigDetails(&bind.CallOpts{ - Context: context.Background(), - }, uint8(pluginType)) - if err != nil { - return err - } - // TODO: assertions to be done as part of full state - // resprentation validation CCIP-3047 - if mapOfframpOCR3Configs[pluginType].ConfigDigest != ocrConfig.ConfigInfo.ConfigDigest { - return fmt.Errorf("%s OCR3 config digest mismatch", pluginType.String()) - } - if mapOfframpOCR3Configs[pluginType].F != ocrConfig.ConfigInfo.F { - return fmt.Errorf("%s OCR3 config F mismatch", pluginType.String()) - } - if mapOfframpOCR3Configs[pluginType].IsSignatureVerificationEnabled != ocrConfig.ConfigInfo.IsSignatureVerificationEnabled { - return fmt.Errorf("%s OCR3 config signature verification mismatch", pluginType.String()) - } - if pluginType == cctypes.PluginTypeCCIPCommit { - // only commit will set signers, exec doesn't need them. - for i, signer := range mapOfframpOCR3Configs[pluginType].Signers { - if !bytes.Equal(signer.Bytes(), ocrConfig.Signers[i].Bytes()) { - return fmt.Errorf("%s OCR3 config signer mismatch", pluginType.String()) - } - } - } - for i, transmitter := range mapOfframpOCR3Configs[pluginType].Transmitters { - if !bytes.Equal(transmitter.Bytes(), ocrConfig.Transmitters[i].Bytes()) { - return fmt.Errorf("%s OCR3 config transmitter mismatch", pluginType.String()) - } - } - } - - return nil -} - -func ApplyChainConfigUpdatesOp( - e deployment.Environment, - state CCIPOnChainState, - homeChainSel uint64, - chains []uint64, -) (mcms.Operation, error) { - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - if err != nil { - return mcms.Operation{}, err - } - encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ - GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), - DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), - OptimisticConfirmations: 1, - }) - if err != nil { - return mcms.Operation{}, err - } - var chainConfigUpdates []ccip_home.CCIPHomeChainConfigArgs - for _, chainSel := range chains { - chainConfig := SetupConfigInfo(chainSel, nodes.NonBootstraps().PeerIDs(), - nodes.DefaultF(), encodedExtraChainConfig) - chainConfigUpdates = append(chainConfigUpdates, chainConfig) - } - - addChain, err := state.Chains[homeChainSel].CCIPHome.ApplyChainConfigUpdates( - deployment.SimTransactOpts(), - nil, - chainConfigUpdates, - ) - if err != nil { - return mcms.Operation{}, err - } - return mcms.Operation{ - To: state.Chains[homeChainSel].CCIPHome.Address(), - Data: addChain.Data(), - Value: big.NewInt(0), - }, nil -} diff --git a/deployment/ccip/changeset/deploy_test.go b/deployment/ccip/changeset/deploy_test.go deleted file mode 100644 index fb5729c5b77..00000000000 --- a/deployment/ccip/changeset/deploy_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package changeset - -import ( - "encoding/json" - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestDeployCCIPContracts(t *testing.T) { - lggr := logger.TestLogger(t) - e := NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 2, 4, nil) - // Deploy all the CCIP contracts. - state, err := LoadOnchainState(e.Env) - require.NoError(t, err) - snap, err := state.View(e.Env.AllChainSelectors()) - require.NoError(t, err) - - // Assert expect every deployed address to be in the address book. - // TODO (CCIP-3047): Add the rest of CCIPv2 representation - b, err := json.MarshalIndent(snap, "", " ") - require.NoError(t, err) - fmt.Println(string(b)) -} diff --git a/deployment/ccip/changeset/home_chain.go b/deployment/ccip/changeset/home_chain.go deleted file mode 100644 index e88db2bcfe0..00000000000 --- a/deployment/ccip/changeset/home_chain.go +++ /dev/null @@ -1,74 +0,0 @@ -package changeset - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" -) - -var _ deployment.ChangeSet[DeployHomeChainConfig] = DeployHomeChain - -// DeployHomeChain is a separate changeset because it is a standalone deployment performed once in home chain for the entire CCIP deployment. -func DeployHomeChain(env deployment.Environment, cfg DeployHomeChainConfig) (deployment.ChangesetOutput, error) { - err := cfg.Validate() - if err != nil { - return deployment.ChangesetOutput{}, errors.Wrapf(deployment.ErrInvalidConfig, "%v", err) - } - ab := deployment.NewMemoryAddressBook() - // Note we also deploy the cap reg. - _, err = deployHomeChain(env.Logger, env, ab, env.Chains[cfg.HomeChainSel], cfg.RMNStaticConfig, cfg.RMNDynamicConfig, cfg.NodeOperators, cfg.NodeP2PIDsPerNodeOpAdmin) - if err != nil { - env.Logger.Errorw("Failed to deploy cap reg", "err", err, "addresses", env.ExistingAddresses) - return deployment.ChangesetOutput{ - AddressBook: ab, - }, err - } - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{}, - AddressBook: ab, - JobSpecs: nil, - }, nil -} - -type DeployHomeChainConfig struct { - HomeChainSel uint64 - RMNStaticConfig rmn_home.RMNHomeStaticConfig - RMNDynamicConfig rmn_home.RMNHomeDynamicConfig - NodeOperators []capabilities_registry.CapabilitiesRegistryNodeOperator - NodeP2PIDsPerNodeOpAdmin map[string][][32]byte -} - -func (c DeployHomeChainConfig) Validate() error { - if c.HomeChainSel == 0 { - return fmt.Errorf("home chain selector must be set") - } - if c.RMNDynamicConfig.OffchainConfig == nil { - return fmt.Errorf("offchain config for RMNHomeDynamicConfig must be set") - } - if c.RMNStaticConfig.OffchainConfig == nil { - return fmt.Errorf("offchain config for RMNHomeStaticConfig must be set") - } - if len(c.NodeOperators) == 0 { - return fmt.Errorf("node operators must be set") - } - for _, nop := range c.NodeOperators { - if nop.Admin == (common.Address{}) { - return fmt.Errorf("node operator admin address must be set") - } - if nop.Name == "" { - return fmt.Errorf("node operator name must be set") - } - if len(c.NodeP2PIDsPerNodeOpAdmin[nop.Name]) == 0 { - return fmt.Errorf("node operator %s must have node p2p ids provided", nop.Name) - } - } - - return nil -} diff --git a/deployment/ccip/changeset/initial_add_chain.go b/deployment/ccip/changeset/initial_add_chain.go deleted file mode 100644 index 841f2014204..00000000000 --- a/deployment/ccip/changeset/initial_add_chain.go +++ /dev/null @@ -1,208 +0,0 @@ -package changeset - -import ( - "fmt" - "os" - "slices" - "sort" - "time" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - "github.com/smartcontractkit/chainlink/deployment/common/types" -) - -var _ deployment.ChangeSet[NewChainsConfig] = ConfigureNewChains - -// ConfigureNewChains enables new chains as destination for CCIP -// It performs the following steps: -// - AddChainConfig + AddDON (candidate->primary promotion i.e. init) on the home chain -// - SetOCR3Config on the remote chain -// ConfigureNewChains assumes that the home chain is already enabled and all CCIP contracts are already deployed. -func ConfigureNewChains(env deployment.Environment, c NewChainsConfig) (deployment.ChangesetOutput, error) { - if err := c.Validate(); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("invalid NewChainsConfig: %w", err) - } - err := configureChain(env, c) - if err != nil { - env.Logger.Errorw("Failed to configure chain", "err", err) - return deployment.ChangesetOutput{}, deployment.MaybeDataErr(err) - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{}, - AddressBook: nil, - JobSpecs: nil, - }, nil -} - -type USDCConfig struct { - EnabledChains []uint64 - USDCAttestationConfig - CCTPTokenConfig map[ccipocr3.ChainSelector]pluginconfig.USDCCCTPTokenConfig -} - -func (cfg USDCConfig) EnabledChainMap() map[uint64]bool { - m := make(map[uint64]bool) - for _, chain := range cfg.EnabledChains { - m[chain] = true - } - return m -} - -func (cfg USDCConfig) ToTokenDataObserverConfig() []pluginconfig.TokenDataObserverConfig { - return []pluginconfig.TokenDataObserverConfig{{ - Type: pluginconfig.USDCCCTPHandlerType, - Version: "1.0", - USDCCCTPObserverConfig: &pluginconfig.USDCCCTPObserverConfig{ - Tokens: cfg.CCTPTokenConfig, - AttestationAPI: cfg.API, - AttestationAPITimeout: cfg.APITimeout, - AttestationAPIInterval: cfg.APIInterval, - }, - }} -} - -type USDCAttestationConfig struct { - API string - APITimeout *config.Duration - APIInterval *config.Duration -} - -type CCIPOCRParams struct { - OCRParameters types.OCRParameters - CommitOffChainConfig pluginconfig.CommitOffchainConfig - ExecuteOffChainConfig pluginconfig.ExecuteOffchainConfig -} - -func (p CCIPOCRParams) Validate() error { - if err := p.OCRParameters.Validate(); err != nil { - return fmt.Errorf("invalid OCR parameters: %w", err) - } - if err := p.CommitOffChainConfig.Validate(); err != nil { - return fmt.Errorf("invalid commit off-chain config: %w", err) - } - if err := p.ExecuteOffChainConfig.Validate(); err != nil { - return fmt.Errorf("invalid execute off-chain config: %w", err) - } - return nil -} - -type NewChainsConfig struct { - HomeChainSel uint64 - FeedChainSel uint64 - ChainsToDeploy []uint64 - TokenConfig TokenConfig - USDCConfig USDCConfig - // For setting OCR configuration - OCRSecrets deployment.OCRSecrets - OCRParams map[uint64]CCIPOCRParams -} - -func (c NewChainsConfig) Validate() error { - if err := deployment.IsValidChainSelector(c.HomeChainSel); err != nil { - return fmt.Errorf("invalid home chain selector: %d - %w", c.HomeChainSel, err) - } - if err := deployment.IsValidChainSelector(c.FeedChainSel); err != nil { - return fmt.Errorf("invalid feed chain selector: %d - %w", c.FeedChainSel, err) - } - mapChainsToDeploy := make(map[uint64]bool) - for _, cs := range c.ChainsToDeploy { - mapChainsToDeploy[cs] = true - if err := deployment.IsValidChainSelector(cs); err != nil { - return fmt.Errorf("invalid chain selector: %d - %w", cs, err) - } - } - for token := range c.TokenConfig.TokenSymbolToInfo { - if err := c.TokenConfig.TokenSymbolToInfo[token].Validate(); err != nil { - return fmt.Errorf("invalid token config for token %s: %w", token, err) - } - } - if c.OCRSecrets.IsEmpty() { - return fmt.Errorf("no OCR secrets provided") - } - usdcEnabledChainMap := c.USDCConfig.EnabledChainMap() - for chain := range usdcEnabledChainMap { - if _, exists := mapChainsToDeploy[chain]; !exists { - return fmt.Errorf("chain %d is not in chains to deploy", chain) - } - if err := deployment.IsValidChainSelector(chain); err != nil { - return fmt.Errorf("invalid chain selector: %d - %w", chain, err) - } - } - for chain := range c.USDCConfig.CCTPTokenConfig { - if _, exists := mapChainsToDeploy[uint64(chain)]; !exists { - return fmt.Errorf("chain %d is not in chains to deploy", chain) - } - if _, exists := usdcEnabledChainMap[uint64(chain)]; !exists { - return fmt.Errorf("chain %d is not enabled in USDC config", chain) - } - if err := deployment.IsValidChainSelector(uint64(chain)); err != nil { - return fmt.Errorf("invalid chain selector: %d - %w", chain, err) - } - } - // Validate OCR params - var ocrChains []uint64 - for chain, ocrParams := range c.OCRParams { - ocrChains = append(ocrChains, chain) - if _, exists := mapChainsToDeploy[chain]; !exists { - return fmt.Errorf("chain %d is not in chains to deploy", chain) - } - if err := ocrParams.Validate(); err != nil { - return fmt.Errorf("invalid OCR params for chain %d: %w", chain, err) - } - } - sort.Slice(ocrChains, func(i, j int) bool { return ocrChains[i] < ocrChains[j] }) - sort.Slice(c.ChainsToDeploy, func(i, j int) bool { return c.ChainsToDeploy[i] < c.ChainsToDeploy[j] }) - if !slices.Equal(ocrChains, c.ChainsToDeploy) { - return fmt.Errorf("mismatch in given OCR params and chains to deploy") - } - return nil -} - -func DefaultOCRParams( - feedChainSel uint64, - tokenInfo map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo, -) CCIPOCRParams { - return CCIPOCRParams{ - OCRParameters: types.OCRParameters{ - DeltaProgress: internal.DeltaProgress, - DeltaResend: internal.DeltaResend, - DeltaInitial: internal.DeltaInitial, - DeltaRound: internal.DeltaRound, - DeltaGrace: internal.DeltaGrace, - DeltaCertifiedCommitRequest: internal.DeltaCertifiedCommitRequest, - DeltaStage: internal.DeltaStage, - Rmax: internal.Rmax, - MaxDurationQuery: internal.MaxDurationQuery, - MaxDurationObservation: internal.MaxDurationObservation, - MaxDurationShouldAcceptAttestedReport: internal.MaxDurationShouldAcceptAttestedReport, - MaxDurationShouldTransmitAcceptedReport: internal.MaxDurationShouldTransmitAcceptedReport, - }, - ExecuteOffChainConfig: pluginconfig.ExecuteOffchainConfig{ - BatchGasLimit: internal.BatchGasLimit, - RelativeBoostPerWaitHour: internal.RelativeBoostPerWaitHour, - InflightCacheExpiry: *config.MustNewDuration(internal.InflightCacheExpiry), - RootSnoozeTime: *config.MustNewDuration(internal.RootSnoozeTime), - MessageVisibilityInterval: *config.MustNewDuration(internal.FirstBlockAge), - BatchingStrategyID: internal.BatchingStrategyID, - }, - CommitOffChainConfig: pluginconfig.CommitOffchainConfig{ - RemoteGasPriceBatchWriteFrequency: *config.MustNewDuration(internal.RemoteGasPriceBatchWriteFrequency), - TokenPriceBatchWriteFrequency: *config.MustNewDuration(internal.TokenPriceBatchWriteFrequency), - TokenInfo: tokenInfo, - PriceFeedChainSelector: ccipocr3.ChainSelector(feedChainSel), - NewMsgScanBatchSize: merklemulti.MaxNumberTreeLeaves, - MaxReportTransmissionCheckAttempts: 5, - RMNEnabled: os.Getenv("ENABLE_RMN") == "true", // only enabled in manual test - RMNSignaturesTimeout: 30 * time.Minute, - MaxMerkleTreeSize: merklemulti.MaxNumberTreeLeaves, - SignObservationPrefix: "chainlink ccip 1.6 rmn observation", - }, - } -} diff --git a/deployment/ccip/changeset/initial_deploy_test.go b/deployment/ccip/changeset/initial_deploy_test.go index 0318af8ffbb..97e516c8f94 100644 --- a/deployment/ccip/changeset/initial_deploy_test.go +++ b/deployment/ccip/changeset/initial_deploy_test.go @@ -7,6 +7,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -15,9 +16,13 @@ import ( func TestInitialDeploy(t *testing.T) { lggr := logger.TestLogger(t) - tenv := NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 3, 4, nil) + tenv := NewMemoryEnvironmentWithJobsAndContracts(t, lggr, memory.MemoryEnvironmentConfig{ + Chains: 3, + Nodes: 4, + Bootstraps: 1, + NumOfUsersPerChain: 1, + }, nil) e := tenv.Env - state, err := LoadOnchainState(e) require.NoError(t, err) // Add all lanes @@ -37,13 +42,21 @@ func TestInitialDeploy(t *testing.T) { require.NoError(t, err) block := latesthdr.Number.Uint64() startBlocks[dest] = &block - msgSentEvent := TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), - Data: []byte("hello"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) + require.GreaterOrEqual(t, len(tenv.Users[src]), 1) + msgSentEvent, err := DoSendRequest(t, e, state, + WithTestRouter(false), + WithSourceChain(src), + WithDestChain(dest), + WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }), + WithSender(tenv.Users[src][0]), + ) + require.NoError(t, err) expectedSeqNum[SourceDestPair{ SourceChainSelector: src, DestChainSelector: dest, diff --git a/deployment/ccip/changeset/internal/deploy_home_chain.go b/deployment/ccip/changeset/internal/deploy_home_chain.go index 7b45a52a436..6328c329b9a 100644 --- a/deployment/ccip/changeset/internal/deploy_home_chain.go +++ b/deployment/ccip/changeset/internal/deploy_home_chain.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" @@ -30,7 +31,7 @@ const ( RemoteGasPriceBatchWriteFrequency = 30 * time.Minute TokenPriceBatchWriteFrequency = 30 * time.Minute BatchGasLimit = 6_500_000 - RelativeBoostPerWaitHour = 1.5 + RelativeBoostPerWaitHour = 10000.5 InflightCacheExpiry = 10 * time.Minute RootSnoozeTime = 30 * time.Minute BatchingStrategyID = 0 @@ -173,6 +174,7 @@ func BuildSetOCR3ConfigArgs( } func SetupExecDON( + lggr logger.Logger, donID uint32, execConfig ccip_home.CCIPHomeOCR3Config, capReg *capabilities_registry.CapabilitiesRegistry, @@ -212,6 +214,7 @@ func SetupExecDON( if _, err := deployment.ConfirmIfNoError(home, tx, err); err != nil { return fmt.Errorf("confirm update don w/ exec config: %w", err) } + lggr.Infow("Updated DON with exec config", "chain", home.String(), "donID", donID, "txHash", tx.Hash().Hex(), "setCandidateCall", encodedSetCandidateCall) execCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, execConfig.PluginType) if err != nil { @@ -221,7 +224,7 @@ func SetupExecDON( if execCandidateDigest == [32]byte{} { return fmt.Errorf("candidate digest is empty, expected nonempty") } - + lggr.Infow("Got exec candidate digest", "chain", home.String(), "donID", donID, "execCandidateDigest", execCandidateDigest) // promote candidate call encodedPromotionCall, err := CCIPHomeABI.Pack( "promoteCandidateAndRevokeActive", @@ -257,6 +260,7 @@ func SetupExecDON( if bn == 0 { return fmt.Errorf("UpdateDON tx not confirmed") } + lggr.Infow("Promoted exec candidate", "chain", home.String(), "donID", donID, "txHash", tx.Hash().Hex(), "promotionCall", encodedPromotionCall) // check if candidate digest is promoted pEvent, err := ccipHome.FilterConfigPromoted(&bind.FilterOpts{ Context: context.Background(), @@ -293,14 +297,20 @@ func SetupExecDON( return fmt.Errorf("get all exec configs 2nd time: %w", err) } - // print the above info - fmt.Printf("completed exec DON creation and promotion: donID: %d execCandidateDigest: %x, execActiveDigest: %x, execCandidateDigestFromGetAllConfigs: %x, execActiveDigestFromGetAllConfigs: %x\n", - donID, execCandidateDigest, execActiveDigest, execConfigs.CandidateConfig.ConfigDigest, execConfigs.ActiveConfig.ConfigDigest) + // log the above info + lggr.Infow("completed exec DON creation and promotion", + "donID", donID, + "execCandidateDigest", execCandidateDigest, + "execActiveDigest", execActiveDigest, + "execCandidateDigestFromGetAllConfigs", execConfigs.CandidateConfig.ConfigDigest, + "execActiveDigestFromGetAllConfigs", execConfigs.ActiveConfig.ConfigDigest, + ) return nil } func SetupCommitDON( + lggr logger.Logger, donID uint32, commitConfig ccip_home.CCIPHomeOCR3Config, capReg *capabilities_registry.CapabilitiesRegistry, @@ -331,7 +341,7 @@ func SetupCommitDON( if _, err := deployment.ConfirmIfNoError(home, tx, err); err != nil { return fmt.Errorf("confirm add don w/ commit config: %w", err) } - + lggr.Debugw("Added DON with commit config", "chain", home.String(), "donID", donID, "txHash", tx.Hash().Hex(), "setCandidateCall", encodedSetCandidateCall) commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, commitConfig.PluginType) if err != nil { return fmt.Errorf("get commit candidate digest: %w", err) @@ -340,7 +350,7 @@ func SetupCommitDON( if commitCandidateDigest == [32]byte{} { return fmt.Errorf("candidate digest is empty, expected nonempty") } - fmt.Printf("commit candidate digest after setCandidate: %x\n", commitCandidateDigest) + lggr.Debugw("Got commit candidate digest", "chain", home.String(), "donID", donID, "commitCandidateDigest", commitCandidateDigest) encodedPromotionCall, err := CCIPHomeABI.Pack( "promoteCandidateAndRevokeActive", @@ -373,6 +383,7 @@ func SetupCommitDON( if _, err := deployment.ConfirmIfNoError(home, tx, err); err != nil { return fmt.Errorf("confirm update don w/ commit config: %w", err) } + lggr.Debugw("Promoted commit candidate", "chain", home.String(), "donID", donID, "txHash", tx.Hash().Hex(), "promotionCall", encodedPromotionCall) // check that candidate digest is empty. commitCandidateDigest, err = ccipHome.GetCandidateDigest(nil, donID, commitConfig.PluginType) @@ -399,9 +410,14 @@ func SetupCommitDON( return fmt.Errorf("get all commit configs 2nd time: %w", err) } - // print the above information - fmt.Printf("completed commit DON creation and promotion: donID: %d, commitCandidateDigest: %x, commitActiveDigest: %x, commitCandidateDigestFromGetAllConfigs: %x, commitActiveDigestFromGetAllConfigs: %x\n", - donID, commitCandidateDigest, commitActiveDigest, commitConfigs.CandidateConfig.ConfigDigest, commitConfigs.ActiveConfig.ConfigDigest) + // log the above information + lggr.Infow("completed commit DON creation and promotion", + "donID", donID, + "commitCandidateDigest", commitCandidateDigest, + "commitActiveDigest", commitActiveDigest, + "commitCandidateDigestFromGetAllConfigs", commitConfigs.CandidateConfig.ConfigDigest, + "commitActiveDigestFromGetAllConfigs", commitConfigs.ActiveConfig.ConfigDigest, + ) return nil } diff --git a/deployment/ccip/changeset/jobspec.go b/deployment/ccip/changeset/jobspec.go deleted file mode 100644 index 04b658202ea..00000000000 --- a/deployment/ccip/changeset/jobspec.go +++ /dev/null @@ -1,24 +0,0 @@ -package changeset - -import ( - "github.com/pkg/errors" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" -) - -var _ deployment.ChangeSet[any] = CCIPCapabilityJobspec - -// CCIPCapabilityJobspec returns the job specs for the CCIP capability. -// The caller needs to propose these job specs to the offchain system. -func CCIPCapabilityJobspec(env deployment.Environment, _ any) (deployment.ChangesetOutput, error) { - js, err := NewCCIPJobSpecs(env.NodeIDs, env.Offchain) - if err != nil { - return deployment.ChangesetOutput{}, errors.Wrapf(err, "failed to create job specs") - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{}, - AddressBook: nil, - JobSpecs: js, - }, nil -} diff --git a/deployment/ccip/changeset/ownership.go b/deployment/ccip/changeset/ownership.go deleted file mode 100644 index 4287363b8a6..00000000000 --- a/deployment/ccip/changeset/ownership.go +++ /dev/null @@ -1,37 +0,0 @@ -package changeset - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/deployment" -) - -func TransferAllOwnership(t *testing.T, state CCIPOnChainState, homeCS uint64, e deployment.Environment) { - for _, source := range e.AllChainSelectors() { - if state.Chains[source].OnRamp != nil { - tx, err := state.Chains[source].OnRamp.TransferOwnership(e.Chains[source].DeployerKey, state.Chains[source].Timelock.Address()) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(e.Chains[source], tx, err) - require.NoError(t, err) - } - if state.Chains[source].FeeQuoter != nil { - tx, err := state.Chains[source].FeeQuoter.TransferOwnership(e.Chains[source].DeployerKey, state.Chains[source].Timelock.Address()) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(e.Chains[source], tx, err) - require.NoError(t, err) - } - // TODO: add offramp and commit stores - - } - // Transfer CR contract ownership - tx, err := state.Chains[homeCS].CapabilityRegistry.TransferOwnership(e.Chains[homeCS].DeployerKey, state.Chains[homeCS].Timelock.Address()) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(e.Chains[homeCS], tx, err) - require.NoError(t, err) - tx, err = state.Chains[homeCS].CCIPHome.TransferOwnership(e.Chains[homeCS].DeployerKey, state.Chains[homeCS].Timelock.Address()) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(e.Chains[homeCS], tx, err) - require.NoError(t, err) -} diff --git a/deployment/ccip/changeset/prerequisites.go b/deployment/ccip/changeset/prerequisites.go deleted file mode 100644 index 34780809827..00000000000 --- a/deployment/ccip/changeset/prerequisites.go +++ /dev/null @@ -1,58 +0,0 @@ -package changeset - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" -) - -var ( - _ deployment.ChangeSet[DeployPrerequisiteConfig] = DeployPrerequisites -) - -// DeployPrerequisites deploys the pre-requisite contracts for CCIP -// pre-requisite contracts are the contracts which can be reused from previous versions of CCIP -// Or the contracts which are already deployed on the chain ( for example, tokens, feeds, etc) -// Caller should update the environment's address book with the returned addresses. -func DeployPrerequisites(env deployment.Environment, cfg DeployPrerequisiteConfig) (deployment.ChangesetOutput, error) { - err := cfg.Validate() - if err != nil { - return deployment.ChangesetOutput{}, errors.Wrapf(deployment.ErrInvalidConfig, "%v", err) - } - ab := deployment.NewMemoryAddressBook() - err = deployPrerequisiteChainContracts(env, ab, cfg.ChainSelectors, cfg.Opts...) - if err != nil { - env.Logger.Errorw("Failed to deploy prerequisite contracts", "err", err, "addressBook", ab) - return deployment.ChangesetOutput{ - AddressBook: ab, - }, fmt.Errorf("failed to deploy prerequisite contracts: %w", err) - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{}, - AddressBook: ab, - JobSpecs: nil, - }, nil -} - -type DeployPrerequisiteConfig struct { - ChainSelectors []uint64 - Opts []PrerequisiteOpt - // TODO handle tokens and feeds in prerequisite config - Tokens map[TokenSymbol]common.Address - Feeds map[TokenSymbol]common.Address -} - -func (c DeployPrerequisiteConfig) Validate() error { - mapAllChainSelectors := make(map[uint64]struct{}) - for _, cs := range c.ChainSelectors { - mapAllChainSelectors[cs] = struct{}{} - if err := deployment.IsValidChainSelector(cs); err != nil { - return fmt.Errorf("invalid chain selector: %d - %w", cs, err) - } - } - return nil -} diff --git a/deployment/ccip/changeset/propose.go b/deployment/ccip/changeset/propose.go deleted file mode 100644 index 1b7d928f414..00000000000 --- a/deployment/ccip/changeset/propose.go +++ /dev/null @@ -1,128 +0,0 @@ -package changeset - -import ( - "fmt" - "math/big" - "time" - - mapset "github.com/deckarep/golang-set/v2" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - chainsel "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink/deployment" -) - -func GenerateAcceptOwnershipProposal( - state CCIPOnChainState, - homeChain uint64, - chains []uint64, -) (*timelock.MCMSWithTimelockProposal, error) { - // TODO: Accept rest of contracts - var batches []timelock.BatchChainOperation - for _, sel := range chains { - chain, _ := chainsel.ChainBySelector(sel) - acceptOnRamp, err := state.Chains[sel].OnRamp.AcceptOwnership(deployment.SimTransactOpts()) - if err != nil { - return nil, err - } - acceptFeeQuoter, err := state.Chains[sel].FeeQuoter.AcceptOwnership(deployment.SimTransactOpts()) - if err != nil { - return nil, err - } - chainSel := mcms.ChainIdentifier(chain.Selector) - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: chainSel, - Batch: []mcms.Operation{ - { - To: state.Chains[sel].OnRamp.Address(), - Data: acceptOnRamp.Data(), - Value: big.NewInt(0), - }, - { - To: state.Chains[sel].FeeQuoter.Address(), - Data: acceptFeeQuoter.Data(), - Value: big.NewInt(0), - }, - }, - }) - } - - acceptCR, err := state.Chains[homeChain].CapabilityRegistry.AcceptOwnership(deployment.SimTransactOpts()) - if err != nil { - return nil, err - } - acceptCCIPConfig, err := state.Chains[homeChain].CCIPHome.AcceptOwnership(deployment.SimTransactOpts()) - if err != nil { - return nil, err - } - homeChainID := mcms.ChainIdentifier(homeChain) - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: homeChainID, - Batch: []mcms.Operation{ - { - To: state.Chains[homeChain].CapabilityRegistry.Address(), - Data: acceptCR.Data(), - Value: big.NewInt(0), - }, - { - To: state.Chains[homeChain].CCIPHome.Address(), - Data: acceptCCIPConfig.Data(), - Value: big.NewInt(0), - }, - }, - }) - - return BuildProposalFromBatches(state, batches, "accept ownership operations", 0) -} - -func BuildProposalMetadata(state CCIPOnChainState, chains []uint64) (map[mcms.ChainIdentifier]common.Address, map[mcms.ChainIdentifier]mcms.ChainMetadata, error) { - tlAddressMap := make(map[mcms.ChainIdentifier]common.Address) - metaDataPerChain := make(map[mcms.ChainIdentifier]mcms.ChainMetadata) - for _, sel := range chains { - chainId := mcms.ChainIdentifier(sel) - tlAddressMap[chainId] = state.Chains[sel].Timelock.Address() - mcm := state.Chains[sel].ProposerMcm - opCount, err := mcm.GetOpCount(nil) - if err != nil { - return nil, nil, err - } - metaDataPerChain[chainId] = mcms.ChainMetadata{ - StartingOpCount: opCount.Uint64(), - MCMAddress: mcm.Address(), - } - } - return tlAddressMap, metaDataPerChain, nil -} - -// Given batches of operations, we build the metadata and timelock addresses of those opartions -// We then return a proposal that can be executed and signed -func BuildProposalFromBatches(state CCIPOnChainState, batches []timelock.BatchChainOperation, description string, minDelay time.Duration) (*timelock.MCMSWithTimelockProposal, error) { - if len(batches) == 0 { - return nil, fmt.Errorf("no operations in batch") - } - - chains := mapset.NewSet[uint64]() - for _, op := range batches { - chains.Add(uint64(op.ChainIdentifier)) - } - - tls, mcmsMd, err := BuildProposalMetadata(state, chains.ToSlice()) - if err != nil { - return nil, err - } - - return timelock.NewMCMSWithTimelockProposal( - "1", - 2004259681, // TODO: should be parameterized and based on current block timestamp. - []mcms.Signature{}, - false, - mcmsMd, - tls, - description, - batches, - timelock.Schedule, - minDelay.String(), - ) -} diff --git a/deployment/ccip/changeset/save_existing_test.go b/deployment/ccip/changeset/save_existing_test.go index 93f3d7e067d..080ed80481a 100644 --- a/deployment/ccip/changeset/save_existing_test.go +++ b/deployment/ccip/changeset/save_existing_test.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -29,7 +30,7 @@ func TestSaveExistingCCIP(t *testing.T) { ExistingContracts: []commonchangeset.Contract{ { Address: common.BigToAddress(big.NewInt(1)), - TypeAndVersion: deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0), + TypeAndVersion: deployment.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0), ChainSelector: chain1, }, { diff --git a/deployment/ccip/changeset/state.go b/deployment/ccip/changeset/state.go index 61b58b59af6..22ae59fc360 100644 --- a/deployment/ccip/changeset/state.go +++ b/deployment/ccip/changeset/state.go @@ -3,6 +3,9 @@ package changeset import ( "fmt" + burn_mint_token_pool "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool_1_4_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/erc20" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_messenger" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool" @@ -10,7 +13,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/view" @@ -45,10 +47,42 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" ) +var ( + MockRMN deployment.ContractType = "MockRMN" + RMNRemote deployment.ContractType = "RMNRemote" + ARMProxy deployment.ContractType = "ARMProxy" + WETH9 deployment.ContractType = "WETH9" + Router deployment.ContractType = "Router" + CommitStore deployment.ContractType = "CommitStore" + TokenAdminRegistry deployment.ContractType = "TokenAdminRegistry" + RegistryModule deployment.ContractType = "RegistryModuleOwnerCustom" + NonceManager deployment.ContractType = "NonceManager" + FeeQuoter deployment.ContractType = "FeeQuoter" + CCIPHome deployment.ContractType = "CCIPHome" + CCIPConfig deployment.ContractType = "CCIPConfig" + RMNHome deployment.ContractType = "RMNHome" + OnRamp deployment.ContractType = "OnRamp" + OffRamp deployment.ContractType = "OffRamp" + CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" + PriceFeed deployment.ContractType = "PriceFeed" + // Note test router maps to a regular router contract. + TestRouter deployment.ContractType = "TestRouter" + Multicall3 deployment.ContractType = "Multicall3" + CCIPReceiver deployment.ContractType = "CCIPReceiver" + BurnMintToken deployment.ContractType = "BurnMintToken" + BurnMintTokenPool deployment.ContractType = "BurnMintTokenPool" + USDCToken deployment.ContractType = "USDCToken" + USDCMockTransmitter deployment.ContractType = "USDCMockTransmitter" + USDCTokenMessenger deployment.ContractType = "USDCTokenMessenger" + USDCTokenPool deployment.ContractType = "USDCTokenPool" +) + // CCIPChainState holds a Go binding for all the currently deployed CCIP contracts // on a chain. If a binding is nil, it means here is no such contract on the chain. type CCIPChainState struct { commoncs.MCMSWithTimelockState + commoncs.LinkTokenState + commoncs.StaticLinkTokenState OnRamp *onramp.OnRamp OffRamp *offramp.OffRamp FeeQuoter *fee_quoter.FeeQuoter @@ -69,13 +103,12 @@ type CCIPChainState struct { Weth9 *weth9.WETH9 RMNRemote *rmn_remote.RMNRemote MockRMN *mock_rmn_contract.MockRMNContract - // TODO: May need to support older link too - LinkToken *burn_mint_erc677.BurnMintERC677 // Map between token Descriptor (e.g. LinkSymbol, WethSymbol) // and the respective token contract // This is more of an illustration of how we'll have tokens, and it might need some work later to work properly. // Not all tokens will be burn and mint tokens. - BurnMintTokens677 map[TokenSymbol]*burn_mint_erc677.BurnMintERC677 + BurnMintTokens677 map[TokenSymbol]*burn_mint_erc677.BurnMintERC677 + BurnMintTokenPools map[TokenSymbol]*burn_mint_token_pool.BurnMintTokenPool // Map between token Symbol (e.g. LinkSymbol, WethSymbol) // and the respective aggregator USD feed contract USDFeeds map[TokenSymbol]*aggregator_v3_interface.AggregatorV3Interface @@ -101,35 +134,35 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { if c.Router != nil { routerView, err := v1_2.GenerateRouterView(c.Router) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate router view for router %s", c.Router.Address().String()) } chainView.Router[c.Router.Address().Hex()] = routerView } if c.TokenAdminRegistry != nil { taView, err := v1_5.GenerateTokenAdminRegistryView(c.TokenAdminRegistry) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate token admin registry view for token admin registry %s", c.TokenAdminRegistry.Address().String()) } chainView.TokenAdminRegistry[c.TokenAdminRegistry.Address().Hex()] = taView } if c.NonceManager != nil { nmView, err := v1_6.GenerateNonceManagerView(c.NonceManager) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate nonce manager view for nonce manager %s", c.NonceManager.Address().String()) } chainView.NonceManager[c.NonceManager.Address().Hex()] = nmView } if c.RMNRemote != nil { rmnView, err := v1_6.GenerateRMNRemoteView(c.RMNRemote) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate rmn remote view for rmn remote %s", c.RMNRemote.Address().String()) } chainView.RMN[c.RMNRemote.Address().Hex()] = rmnView } if c.FeeQuoter != nil && c.Router != nil && c.TokenAdminRegistry != nil { fqView, err := v1_6.GenerateFeeQuoterView(c.FeeQuoter, c.Router, c.TokenAdminRegistry) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate fee quoter view for fee quoter %s", c.FeeQuoter.Address().String()) } chainView.FeeQuoter[c.FeeQuoter.Address().Hex()] = fqView } @@ -141,7 +174,7 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { c.TokenAdminRegistry, ) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate on ramp view for on ramp %s", c.OnRamp.Address().String()) } chainView.OnRamp[c.OnRamp.Address().Hex()] = onRampView } @@ -152,7 +185,7 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { c.Router, ) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate off ramp view for off ramp %s", c.OffRamp.Address().String()) } chainView.OffRamp[c.OffRamp.Address().Hex()] = offRampView } @@ -160,7 +193,7 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { if c.CommitStore != nil { commitStoreView, err := v1_5.GenerateCommitStoreView(c.CommitStore) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate commit store view for commit store %s", c.CommitStore.Address().String()) } chainView.CommitStore[c.CommitStore.Address().Hex()] = commitStoreView } @@ -168,28 +201,42 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { if c.RMNProxyNew != nil { rmnProxyView, err := v1_0.GenerateRMNProxyView(c.RMNProxyNew) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate rmn proxy view for rmn proxy %s", c.RMNProxyNew.Address().String()) } chainView.RMNProxy[c.RMNProxyNew.Address().Hex()] = rmnProxyView } if c.CapabilityRegistry != nil { capRegView, err := common_v1_0.GenerateCapabilityRegistryView(c.CapabilityRegistry) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate capability registry view for capability registry %s", c.CapabilityRegistry.Address().String()) } chainView.CapabilityRegistry[c.CapabilityRegistry.Address().Hex()] = capRegView } if c.MCMSWithTimelockState.Timelock != nil { mcmsView, err := c.MCMSWithTimelockState.GenerateMCMSWithTimelockView() if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate MCMS with timelock view for MCMS with timelock %s", c.MCMSWithTimelockState.Timelock.Address().String()) } chainView.MCMSWithTimelock = mcmsView } + if c.LinkToken != nil { + linkTokenView, err := c.GenerateLinkView() + if err != nil { + return chainView, errors.Wrapf(err, "failed to generate link token view for link token %s", c.LinkToken.Address().String()) + } + chainView.LinkToken = linkTokenView + } + if c.StaticLinkToken != nil { + staticLinkTokenView, err := c.GenerateStaticLinkView() + if err != nil { + return chainView, err + } + chainView.StaticLinkToken = staticLinkTokenView + } return chainView, nil } -// Onchain state always derivable from an address book. +// CCIPOnChainState state always derivable from an address book. // Offchain state always derivable from a list of nodeIds. // Note can translate this into Go struct needed for MCMS/Docs/UI. type CCIPOnChainState struct { @@ -202,12 +249,7 @@ type CCIPOnChainState struct { func (s CCIPOnChainState) View(chains []uint64) (map[string]view.ChainView, error) { m := make(map[string]view.ChainView) for _, chainSelector := range chains { - // TODO: Need a utility for this - chainid, err := chainsel.ChainIdFromSelector(chainSelector) - if err != nil { - return m, err - } - chainName, err := chainsel.NameFromChainId(chainid) + chainInfo, err := deployment.ChainInfo(chainSelector) if err != nil { return m, err } @@ -219,7 +261,7 @@ func (s CCIPOnChainState) View(chains []uint64) (map[string]view.ChainView, erro if err != nil { return m, err } - m[chainName] = chainView + m[chainInfo.ChainName] = chainView } return m, nil } @@ -250,17 +292,31 @@ func LoadOnchainState(e deployment.Environment) (CCIPOnChainState, error) { // LoadChainState Loads all state for a chain into state func LoadChainState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (CCIPChainState, error) { var state CCIPChainState - mcmsWithTimelock, err := commoncs.LoadMCMSWithTimelockState(chain, addresses) + mcmsWithTimelock, err := commoncs.MaybeLoadMCMSWithTimelockState(chain, addresses) if err != nil { return state, err } state.MCMSWithTimelockState = *mcmsWithTimelock + + linkState, err := commoncs.MaybeLoadLinkTokenState(chain, addresses) + if err != nil { + return state, err + } + state.LinkTokenState = *linkState + staticLinkState, err := commoncs.MaybeLoadStaticLinkTokenState(chain, addresses) + if err != nil { + return state, err + } + state.StaticLinkTokenState = *staticLinkState for address, tvStr := range addresses { switch tvStr.String() { case deployment.NewTypeAndVersion(commontypes.RBACTimelock, deployment.Version1_0_0).String(), deployment.NewTypeAndVersion(commontypes.ProposerManyChainMultisig, deployment.Version1_0_0).String(), deployment.NewTypeAndVersion(commontypes.CancellerManyChainMultisig, deployment.Version1_0_0).String(), - deployment.NewTypeAndVersion(commontypes.BypasserManyChainMultisig, deployment.Version1_0_0).String(): + deployment.NewTypeAndVersion(commontypes.BypasserManyChainMultisig, deployment.Version1_0_0).String(), + deployment.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0).String(), + deployment.NewTypeAndVersion(commontypes.StaticLinkToken, deployment.Version1_0_0).String(): + // Skip common contracts, they are already loaded. continue case deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0).String(): cr, err := capabilities_registry.NewCapabilitiesRegistry(common.HexToAddress(address), chain.Client) @@ -364,12 +420,6 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type return state, err } state.FeeQuoter = fq - case deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0).String(): - lt, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.LinkToken = lt case deployment.NewTypeAndVersion(USDCToken, deployment.Version1_0_0).String(): ut, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) if err != nil { @@ -438,6 +488,40 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type return state, fmt.Errorf("unknown feed description %s", desc) } state.USDFeeds[key] = feed + case deployment.NewTypeAndVersion(BurnMintTokenPool, deployment.Version1_5_1).String(): + pool, err := burn_mint_token_pool.NewBurnMintTokenPool(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + if state.BurnMintTokenPools == nil { + state.BurnMintTokenPools = make(map[TokenSymbol]*burn_mint_token_pool.BurnMintTokenPool) + } + tokAddress, err := pool.GetToken(nil) + if err != nil { + return state, err + } + tok, err := erc20.NewERC20(tokAddress, chain.Client) + if err != nil { + return state, err + } + symbol, err := tok.Symbol(nil) + if err != nil { + return state, err + } + state.BurnMintTokenPools[TokenSymbol(symbol)] = pool + case deployment.NewTypeAndVersion(BurnMintToken, deployment.Version1_0_0).String(): + tok, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + if state.BurnMintTokens677 == nil { + state.BurnMintTokens677 = make(map[TokenSymbol]*burn_mint_erc677.BurnMintERC677) + } + symbol, err := tok.Symbol(nil) + if err != nil { + return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) + } + state.BurnMintTokens677[TokenSymbol(symbol)] = tok default: return state, fmt.Errorf("unknown contract %s", tvStr) } diff --git a/deployment/ccip/changeset/state_test.go b/deployment/ccip/changeset/state_test.go new file mode 100644 index 00000000000..6e679c265dc --- /dev/null +++ b/deployment/ccip/changeset/state_test.go @@ -0,0 +1,24 @@ +package changeset + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestSmokeState(t *testing.T) { + lggr := logger.TestLogger(t) + tenv := NewMemoryEnvironmentWithJobsAndContracts(t, lggr, memory.MemoryEnvironmentConfig{ + Chains: 3, + Nodes: 4, + Bootstraps: 1, + NumOfUsersPerChain: 1, + }, nil) + state, err := LoadOnchainState(tenv.Env) + require.NoError(t, err) + _, err = state.View(tenv.Env.AllChainSelectors()) + require.NoError(t, err) +} diff --git a/deployment/ccip/changeset/test_assertions.go b/deployment/ccip/changeset/test_assertions.go index 770b42e6265..a7d3ecf61f8 100644 --- a/deployment/ccip/changeset/test_assertions.go +++ b/deployment/ccip/changeset/test_assertions.go @@ -199,7 +199,9 @@ func ConfirmCommitForAllWithExpectedSeqNums( ccipocr3.SeqNumRange{ ccipocr3.SeqNum(expectedSeqNum), ccipocr3.SeqNum(expectedSeqNum), - })) + }, + true, + )) }) } } @@ -224,6 +226,73 @@ func ConfirmCommitForAllWithExpectedSeqNums( ) } +type commitReportTracker struct { + seenMessages map[uint64]map[uint64]bool +} + +func newCommitReportTracker(sourceChainSelector uint64, seqNrs ccipocr3.SeqNumRange) commitReportTracker { + seenMessages := make(map[uint64]map[uint64]bool) + seenMessages[sourceChainSelector] = make(map[uint64]bool) + + for i := seqNrs.Start(); i <= seqNrs.End(); i++ { + seenMessages[sourceChainSelector][uint64(i)] = false + } + return commitReportTracker{seenMessages: seenMessages} +} + +func (c *commitReportTracker) visitCommitReport(sourceChainSelector uint64, minSeqNr uint64, maxSeqNr uint64) { + if _, ok := c.seenMessages[sourceChainSelector]; !ok { + return + } + + for i := minSeqNr; i <= maxSeqNr; i++ { + c.seenMessages[sourceChainSelector][i] = true + } +} + +func (c *commitReportTracker) allCommited(sourceChainSelector uint64) bool { + for _, v := range c.seenMessages[sourceChainSelector] { + if !v { + return false + } + } + return true +} + +// ConfirmMultipleCommits waits for multiple ccipocr3.SeqNumRange to be committed by the Offramp. +// Waiting is done in parallel per every sourceChain/destChain (lane) passed as argument. +func ConfirmMultipleCommits( + t *testing.T, + chains map[uint64]deployment.Chain, + state map[uint64]CCIPChainState, + startBlocks map[uint64]*uint64, + enforceSingleCommit bool, + expectedSeqNums map[SourceDestPair]ccipocr3.SeqNumRange, +) error { + errGrp := &errgroup.Group{} + + for sourceDest, seqRange := range expectedSeqNums { + seqRange := seqRange + srcChain := sourceDest.SourceChainSelector + destChain := sourceDest.DestChainSelector + + errGrp.Go(func() error { + _, err := ConfirmCommitWithExpectedSeqNumRange( + t, + chains[srcChain], + chains[destChain], + state[destChain].OffRamp, + startBlocks[destChain], + seqRange, + enforceSingleCommit, + ) + return err + }) + } + + return errGrp.Wait() +} + // ConfirmCommitWithExpectedSeqNumRange waits for a commit report on the destination chain with the expected sequence number range. // startBlock is the block number to start watching from. // If startBlock is nil, it will start watching from the latest block. @@ -234,6 +303,7 @@ func ConfirmCommitWithExpectedSeqNumRange( offRamp *offramp.OffRamp, startBlock *uint64, expectedSeqNumRange ccipocr3.SeqNumRange, + enforceSingleCommit bool, ) (*offramp.OffRampCommitReportAccepted, error) { sink := make(chan *offramp.OffRampCommitReportAccepted) subscription, err := offRamp.WatchCommitReportAccepted(&bind.WatchOpts{ @@ -244,6 +314,8 @@ func ConfirmCommitWithExpectedSeqNumRange( return nil, fmt.Errorf("error to subscribe CommitReportAccepted : %w", err) } + seenMessages := newCommitReportTracker(src.Selector, expectedSeqNumRange) + defer subscription.Unsubscribe() var duration time.Duration deadline, ok := t.Deadline() @@ -279,11 +351,19 @@ func ConfirmCommitWithExpectedSeqNumRange( event := iter.Event if len(event.MerkleRoots) > 0 { for _, mr := range event.MerkleRoots { + t.Logf("Received commit report for [%d, %d] on selector %d from source selector %d expected seq nr range %s, token prices: %v, tx hash: %s", + mr.MinSeqNr, mr.MaxSeqNr, dest.Selector, src.Selector, expectedSeqNumRange.String(), event.PriceUpdates.TokenPriceUpdates, event.Raw.TxHash.String()) + seenMessages.visitCommitReport(src.Selector, mr.MinSeqNr, mr.MaxSeqNr) + if mr.SourceChainSelector == src.Selector && uint64(expectedSeqNumRange.Start()) >= mr.MinSeqNr && uint64(expectedSeqNumRange.End()) <= mr.MaxSeqNr { - t.Logf("Received commit report for [%d, %d] on selector %d from source selector %d expected seq nr range %s, token prices: %v, tx hash: %s", - mr.MinSeqNr, mr.MaxSeqNr, dest.Selector, src.Selector, expectedSeqNumRange.String(), event.PriceUpdates.TokenPriceUpdates, event.Raw.TxHash.String()) + t.Logf("All sequence numbers commited in a single report [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) + return event, nil + } + + if !enforceSingleCommit && seenMessages.allCommited(src.Selector) { + t.Logf("All sequence numbers already commited from range [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) return event, nil } } @@ -299,11 +379,20 @@ func ConfirmCommitWithExpectedSeqNumRange( // Check the interval of sequence numbers and make sure it matches // the expected range. for _, mr := range report.MerkleRoots { + t.Logf("Received commit report for [%d, %d] on selector %d from source selector %d expected seq nr range %s, token prices: %v", + mr.MinSeqNr, mr.MaxSeqNr, dest.Selector, src.Selector, expectedSeqNumRange.String(), report.PriceUpdates.TokenPriceUpdates) + + seenMessages.visitCommitReport(src.Selector, mr.MinSeqNr, mr.MaxSeqNr) + if mr.SourceChainSelector == src.Selector && uint64(expectedSeqNumRange.Start()) >= mr.MinSeqNr && uint64(expectedSeqNumRange.End()) <= mr.MaxSeqNr { - t.Logf("Received commit report for [%d, %d] on selector %d from source selector %d expected seq nr range %s, token prices: %v", - mr.MinSeqNr, mr.MaxSeqNr, dest.Selector, src.Selector, expectedSeqNumRange.String(), report.PriceUpdates.TokenPriceUpdates) + t.Logf("All sequence numbers commited in a single report [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) + return report, nil + } + + if !enforceSingleCommit && seenMessages.allCommited(src.Selector) { + t.Logf("All sequence numbers already commited from range [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) return report, nil } } @@ -394,7 +483,7 @@ func ConfirmExecWithSeqNrs( return nil, fmt.Errorf("no expected sequence numbers provided") } - timer := time.NewTimer(3 * time.Minute) + timer := time.NewTimer(8 * time.Minute) defer timer.Stop() tick := time.NewTicker(3 * time.Second) defer tick.Stop() @@ -509,6 +598,22 @@ func RequireConsistently(t *testing.T, condition func() bool, duration time.Dura } } +func SeqNumberRageToSlice(seqRanges map[SourceDestPair]ccipocr3.SeqNumRange) map[SourceDestPair][]uint64 { + flatten := make(map[SourceDestPair][]uint64) + + for srcDst, seqRange := range seqRanges { + if _, ok := flatten[srcDst]; !ok { + flatten[srcDst] = make([]uint64, 0, seqRange.End()-seqRange.Start()+1) + } + + for i := seqRange.Start(); i <= seqRange.End(); i++ { + flatten[srcDst] = append(flatten[srcDst], uint64(i)) + } + } + + return flatten +} + const ( EXECUTION_STATE_UNTOUCHED = 0 EXECUTION_STATE_INPROGRESS = 1 diff --git a/deployment/ccip/changeset/test_helpers.go b/deployment/ccip/changeset/test_helpers.go index a789a8c45fa..49edb275526 100644 --- a/deployment/ccip/changeset/test_helpers.go +++ b/deployment/ccip/changeset/test_helpers.go @@ -11,6 +11,8 @@ import ( "testing" "time" + "golang.org/x/sync/errgroup" + mapset "github.com/deckarep/golang-set/v2" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common/hexutil" @@ -19,11 +21,11 @@ import ( "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -33,13 +35,15 @@ import ( chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + "github.com/smartcontractkit/chainlink-ccip/pkg/reader" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/logger" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" @@ -90,13 +94,14 @@ type DeployedEnv struct { HomeChainSel uint64 FeedChainSel uint64 ReplayBlocks map[uint64]uint64 + Users map[uint64][]*bind.TransactOpts } func (e *DeployedEnv) SetupJobs(t *testing.T) { ctx := testcontext.Get(t) - jbs, err := NewCCIPJobSpecs(e.Env.NodeIDs, e.Env.Offchain) + out, err := CCIPCapabilityJobspec(e.Env, struct{}{}) require.NoError(t, err) - for nodeID, jobs := range jbs { + for nodeID, jobs := range out.JobSpecs { for _, job := range jobs { // Note these auto-accept _, err := e.Env.Offchain.ProposeJob(ctx, @@ -133,19 +138,23 @@ func DeployTestContracts(t *testing.T, linkPrice *big.Int, wethPrice *big.Int, ) deployment.CapabilityRegistryConfig { - capReg, err := DeployCapReg(lggr, + capReg, err := deployCapReg(lggr, // deploying cap reg for the first time on a blank chain state CCIPOnChainState{ Chains: make(map[uint64]CCIPChainState), }, ab, chains[homeChainSel]) require.NoError(t, err) + _, err = DeployFeeds(lggr, ab, chains[feedChainSel], linkPrice, wethPrice) require.NoError(t, err) + evmChainID, err := chainsel.ChainIdFromSelector(homeChainSel) require.NoError(t, err) + return deployment.CapabilityRegistryConfig{ - EVMChainID: evmChainID, - Contract: capReg.Address, + EVMChainID: evmChainID, + Contract: capReg.Address, + NetworkType: relay.NetworkEVM, } } @@ -181,28 +190,27 @@ func allocateCCIPChainSelectors(chains map[uint64]deployment.Chain) (homeChainSe func NewMemoryEnvironment( t *testing.T, lggr logger.Logger, - numChains int, - numNodes int, + config memory.MemoryEnvironmentConfig, linkPrice *big.Int, wethPrice *big.Int) DeployedEnv { - require.GreaterOrEqual(t, numChains, 2, "numChains must be at least 2 for home and feed chains") - require.GreaterOrEqual(t, numNodes, 4, "numNodes must be at least 4") + require.GreaterOrEqual(t, config.Chains, 2, "numChains must be at least 2 for home and feed chains") + require.GreaterOrEqual(t, config.Nodes, 4, "numNodes must be at least 4") ctx := testcontext.Get(t) - chains := memory.NewMemoryChains(t, numChains) + chains, users := memory.NewMemoryChains(t, config.Chains, config.NumOfUsersPerChain) homeChainSel, feedSel := allocateCCIPChainSelectors(chains) replayBlocks, err := LatestBlocksByChain(ctx, chains) require.NoError(t, err) ab := deployment.NewMemoryAddressBook() crConfig := DeployTestContracts(t, lggr, ab, homeChainSel, feedSel, chains, linkPrice, wethPrice) - nodes := memory.NewNodes(t, zapcore.InfoLevel, chains, numNodes, 1, crConfig) + nodes := memory.NewNodes(t, zapcore.InfoLevel, chains, config.Nodes, config.Bootstraps, crConfig) for _, node := range nodes { require.NoError(t, node.App.Start(ctx)) t.Cleanup(func() { require.NoError(t, node.App.Stop()) }) } - e := memory.NewMemoryEnvironmentFromChainsNodes(t, lggr, chains, nodes) + e := memory.NewMemoryEnvironmentFromChainsNodes(func() context.Context { return ctx }, lggr, chains, nodes) envNodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) require.NoError(t, err) e.ExistingAddresses = ab @@ -221,13 +229,14 @@ func NewMemoryEnvironment( HomeChainSel: homeChainSel, FeedChainSel: feedSel, ReplayBlocks: replayBlocks, + Users: users, } } // NewMemoryEnvironmentWithJobs creates a new CCIP environment // with capreg, fee tokens, feeds, nodes and jobs set up. -func NewMemoryEnvironmentWithJobs(t *testing.T, lggr logger.Logger, numChains int, numNodes int) DeployedEnv { - e := NewMemoryEnvironment(t, lggr, numChains, numNodes, MockLinkPrice, MockWethPrice) +func NewMemoryEnvironmentWithJobs(t *testing.T, lggr logger.Logger, config memory.MemoryEnvironmentConfig) DeployedEnv { + e := NewMemoryEnvironment(t, lggr, config, MockLinkPrice, MockWethPrice) e.SetupJobs(t) return e } @@ -236,13 +245,18 @@ func NewMemoryEnvironmentWithJobs(t *testing.T, lggr logger.Logger, numChains in // We don't need to return exactly the same attestation, because our Mocked USDC contract doesn't rely on any specific // value, but instead of that it just checks if the attestation is present. Therefore, it makes the test a bit simpler // and doesn't require very detailed mocks. Please see tests in chainlink-ccip for detailed tests using real attestations -func mockAttestationResponse() *httptest.Server { +func mockAttestationResponse(isFaulty bool) *httptest.Server { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := `{ "status": "complete", "attestation": "0x9049623e91719ef2aa63c55f357be2529b0e7122ae552c18aff8db58b4633c4d3920ff03d3a6d1ddf11f06bf64d7fd60d45447ac81f527ba628877dc5ca759651b08ffae25a6d3b1411749765244f0a1c131cbfe04430d687a2e12fd9d2e6dc08e118ad95d94ad832332cf3c4f7a4f3da0baa803b7be024b02db81951c0f0714de1b" }` - + if isFaulty { + response = `{ + "status": "pending", + "error": "internal error" + }` + } _, err := w.Write([]byte(response)) if err != nil { panic(err) @@ -252,38 +266,50 @@ func mockAttestationResponse() *httptest.Server { } type TestConfigs struct { - IsUSDC bool - IsMultiCall3 bool + IsUSDC bool + IsUSDCAttestationMissing bool + IsMultiCall3 bool + OCRConfigOverride func(CCIPOCRParams) CCIPOCRParams } -func NewMemoryEnvironmentWithJobsAndContracts(t *testing.T, lggr logger.Logger, numChains int, numNodes int, tCfg *TestConfigs) DeployedEnv { +func NewMemoryEnvironmentWithJobsAndContracts(t *testing.T, lggr logger.Logger, config memory.MemoryEnvironmentConfig, tCfg *TestConfigs) DeployedEnv { var err error - e := NewMemoryEnvironment(t, lggr, numChains, numNodes, MockLinkPrice, MockWethPrice) + e := NewMemoryEnvironment(t, lggr, config, MockLinkPrice, MockWethPrice) allChains := e.Env.AllChainSelectors() - cfg := commontypes.MCMSWithTimelockConfig{ - Canceller: commonchangeset.SingleGroupMCMS(t), - Bypasser: commonchangeset.SingleGroupMCMS(t), - Proposer: commonchangeset.SingleGroupMCMS(t), - TimelockExecutors: e.Env.AllDeployerKeys(), - TimelockMinDelay: big.NewInt(0), - } mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) for _, c := range e.Env.AllChainSelectors() { - mcmsCfg[c] = cfg + mcmsCfg[c] = commontypes.MCMSWithTimelockConfig{ + Canceller: commonchangeset.SingleGroupMCMS(t), + Bypasser: commonchangeset.SingleGroupMCMS(t), + Proposer: commonchangeset.SingleGroupMCMS(t), + TimelockExecutors: e.Env.AllDeployerKeys(), + TimelockMinDelay: big.NewInt(0), + } } - var usdcChains []uint64 - if tCfg != nil && tCfg.IsUSDC { - usdcChains = allChains + var ( + usdcChains []uint64 + isMulticall3 bool + ) + if tCfg != nil { + if tCfg.IsUSDC { + usdcChains = allChains + } + isMulticall3 = tCfg.IsMultiCall3 } // Need to deploy prerequisites first so that we can form the USDC config // no proposals to be made, timelock can be passed as nil here e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: allChains, + }, { Changeset: commonchangeset.WrapChangeSet(DeployPrerequisites), Config: DeployPrerequisiteConfig{ ChainSelectors: allChains, Opts: []PrerequisiteOpt{ WithUSDCChains(usdcChains), + WithMulticall3(isMulticall3), }, }, }, @@ -303,56 +329,57 @@ func NewMemoryEnvironmentWithJobsAndContracts(t *testing.T, lggr logger.Logger, state, err := LoadOnchainState(e.Env) require.NoError(t, err) - tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) - ocrParams := make(map[uint64]CCIPOCRParams) - usdcCCTPConfig := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig) - timelocksPerChain := make(map[uint64]*gethwrappers.RBACTimelock) + // Assert USDC set up as expected. for _, chain := range usdcChains { require.NotNil(t, state.Chains[chain].MockUSDCTokenMessenger) require.NotNil(t, state.Chains[chain].MockUSDCTransmitter) require.NotNil(t, state.Chains[chain].USDCTokenPool) - usdcCCTPConfig[cciptypes.ChainSelector(chain)] = pluginconfig.USDCCCTPTokenConfig{ - SourcePoolAddress: state.Chains[chain].USDCTokenPool.Address().String(), - SourceMessageTransmitterAddr: state.Chains[chain].MockUSDCTransmitter.Address().String(), - } } + // Assert link present require.NotNil(t, state.Chains[e.FeedChainSel].LinkToken) require.NotNil(t, state.Chains[e.FeedChainSel].Weth9) - var usdcCfg USDCAttestationConfig + + tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) + var tokenDataProviders []pluginconfig.TokenDataObserverConfig if len(usdcChains) > 0 { - server := mockAttestationResponse() + server := mockAttestationResponse(tCfg.IsUSDCAttestationMissing) endpoint := server.URL - usdcCfg = USDCAttestationConfig{ - API: endpoint, - APITimeout: commonconfig.MustNewDuration(time.Second), - APIInterval: commonconfig.MustNewDuration(500 * time.Millisecond), - } t.Cleanup(func() { server.Close() }) - } - + cctpContracts := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig) + for _, usdcChain := range usdcChains { + cctpContracts[cciptypes.ChainSelector(usdcChain)] = pluginconfig.USDCCCTPTokenConfig{ + SourcePoolAddress: state.Chains[usdcChain].USDCTokenPool.Address().String(), + SourceMessageTransmitterAddr: state.Chains[usdcChain].MockUSDCTransmitter.Address().String(), + } + } + tokenDataProviders = append(tokenDataProviders, pluginconfig.TokenDataObserverConfig{ + Type: pluginconfig.USDCCCTPHandlerType, + Version: "1.0", + USDCCCTPObserverConfig: &pluginconfig.USDCCCTPObserverConfig{ + Tokens: cctpContracts, + AttestationAPI: endpoint, + AttestationAPITimeout: commonconfig.MustNewDuration(time.Second), + AttestationAPIInterval: commonconfig.MustNewDuration(500 * time.Millisecond), + }}) + } + // Build the per chain config. + chainConfigs := make(map[uint64]CCIPOCRParams) + timelocksPerChain := make(map[uint64]*gethwrappers.RBACTimelock) for _, chain := range allChains { timelocksPerChain[chain] = state.Chains[chain].Timelock tokenInfo := tokenConfig.GetTokenInfo(e.Env.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9) - ocrParams[chain] = DefaultOCRParams(e.FeedChainSel, tokenInfo) + chainConfigs[chain] = DefaultOCRParams(e.FeedChainSel, tokenInfo, tokenDataProviders) } // Deploy second set of changesets to deploy and configure the CCIP contracts. e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ { Changeset: commonchangeset.WrapChangeSet(ConfigureNewChains), Config: NewChainsConfig{ - HomeChainSel: e.HomeChainSel, - FeedChainSel: e.FeedChainSel, - ChainsToDeploy: allChains, - TokenConfig: tokenConfig, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), - USDCConfig: USDCConfig{ - EnabledChains: usdcChains, - USDCAttestationConfig: usdcCfg, - CCTPTokenConfig: usdcCCTPConfig, - }, - OCRParams: ocrParams, + HomeChainSel: e.HomeChainSel, + FeedChainSel: e.FeedChainSel, + ChainConfigByChain: chainConfigs, }, }, { @@ -385,31 +412,29 @@ func NewMemoryEnvironmentWithJobsAndContracts(t *testing.T, lggr logger.Logger, func CCIPSendRequest( e deployment.Environment, state CCIPOnChainState, - src, dest uint64, - testRouter bool, - evm2AnyMessage router.ClientEVM2AnyMessage, + cfg *CCIPSendReqConfig, ) (*types.Transaction, uint64, error) { msg := router.ClientEVM2AnyMessage{ - Receiver: evm2AnyMessage.Receiver, - Data: evm2AnyMessage.Data, - TokenAmounts: evm2AnyMessage.TokenAmounts, - FeeToken: evm2AnyMessage.FeeToken, - ExtraArgs: evm2AnyMessage.ExtraArgs, + Receiver: cfg.Evm2AnyMessage.Receiver, + Data: cfg.Evm2AnyMessage.Data, + TokenAmounts: cfg.Evm2AnyMessage.TokenAmounts, + FeeToken: cfg.Evm2AnyMessage.FeeToken, + ExtraArgs: cfg.Evm2AnyMessage.ExtraArgs, } - r := state.Chains[src].Router - if testRouter { - r = state.Chains[src].TestRouter + r := state.Chains[cfg.SourceChain].Router + if cfg.IsTestRouter { + r = state.Chains[cfg.SourceChain].TestRouter } if msg.FeeToken == common.HexToAddress("0x0") { // fee is in native token - return retryCcipSendUntilNativeFeeIsSufficient(e, r, src, dest, msg) + return retryCcipSendUntilNativeFeeIsSufficient(e, r, cfg) } - tx, err := r.CcipSend(e.Chains[src].DeployerKey, dest, msg) + tx, err := r.CcipSend(cfg.Sender, cfg.DestChain, msg) if err != nil { return nil, 0, errors.Wrap(err, "failed to send CCIP message") } - blockNum, err := e.Chains[src].Confirm(tx) + blockNum, err := e.Chains[cfg.SourceChain].Confirm(tx) if err != nil { return tx, 0, errors.Wrap(err, "failed to confirm CCIP message") } @@ -422,32 +447,30 @@ func CCIPSendRequest( func retryCcipSendUntilNativeFeeIsSufficient( e deployment.Environment, r *router.Router, - src, - dest uint64, - msg router.ClientEVM2AnyMessage, + cfg *CCIPSendReqConfig, ) (*types.Transaction, uint64, error) { const errCodeInsufficientFee = "0x07da6ee6" - defer func() { e.Chains[src].DeployerKey.Value = nil }() + defer func() { cfg.Sender.Value = nil }() for { - fee, err := r.GetFee(&bind.CallOpts{Context: context.Background()}, dest, msg) + fee, err := r.GetFee(&bind.CallOpts{Context: context.Background()}, cfg.DestChain, cfg.Evm2AnyMessage) if err != nil { - return nil, 0, errors.Wrap(deployment.MaybeDataErr(err), "failed to get fee") + return nil, 0, fmt.Errorf("failed to get fee: %w", deployment.MaybeDataErr(err)) } - e.Chains[src].DeployerKey.Value = fee + cfg.Sender.Value = fee - tx, err := r.CcipSend(e.Chains[src].DeployerKey, dest, msg) + tx, err := r.CcipSend(cfg.Sender, cfg.DestChain, cfg.Evm2AnyMessage) if err != nil { - return nil, 0, errors.Wrap(err, "failed to send CCIP message") + return nil, 0, fmt.Errorf("failed to send CCIP message: %w", err) } - blockNum, err := e.Chains[src].Confirm(tx) + blockNum, err := e.Chains[cfg.SourceChain].Confirm(tx) if err != nil { if strings.Contains(err.Error(), errCodeInsufficientFee) { continue } - return nil, 0, errors.Wrap(err, "failed to confirm CCIP message") + return nil, 0, fmt.Errorf("failed to confirm CCIP message: %w", deployment.MaybeDataErr(err)) } return tx, blockNum, nil @@ -481,33 +504,98 @@ func TestSendRequest( testRouter bool, evm2AnyMessage router.ClientEVM2AnyMessage, ) (msgSentEvent *onramp.OnRampCCIPMessageSent) { - t.Logf("Sending CCIP request from chain selector %d to chain selector %d", - src, dest) - tx, blockNum, err := CCIPSendRequest( - e, - state, - src, dest, - testRouter, - evm2AnyMessage, - ) + msgSentEvent, err := DoSendRequest(t, e, state, + WithSender(e.Chains[src].DeployerKey), + WithSourceChain(src), + WithDestChain(dest), + WithTestRouter(testRouter), + WithEvm2AnyMessage(evm2AnyMessage)) require.NoError(t, err) - it, err := state.Chains[src].OnRamp.FilterCCIPMessageSent(&bind.FilterOpts{ + return msgSentEvent +} + +type CCIPSendReqConfig struct { + SourceChain uint64 + DestChain uint64 + IsTestRouter bool + Sender *bind.TransactOpts + Evm2AnyMessage router.ClientEVM2AnyMessage +} + +type SendReqOpts func(*CCIPSendReqConfig) + +func WithSender(sender *bind.TransactOpts) SendReqOpts { + return func(c *CCIPSendReqConfig) { + c.Sender = sender + } +} + +func WithEvm2AnyMessage(msg router.ClientEVM2AnyMessage) SendReqOpts { + return func(c *CCIPSendReqConfig) { + c.Evm2AnyMessage = msg + } +} + +func WithTestRouter(isTestRouter bool) SendReqOpts { + return func(c *CCIPSendReqConfig) { + c.IsTestRouter = isTestRouter + } +} + +func WithSourceChain(sourceChain uint64) SendReqOpts { + return func(c *CCIPSendReqConfig) { + c.SourceChain = sourceChain + } +} + +func WithDestChain(destChain uint64) SendReqOpts { + return func(c *CCIPSendReqConfig) { + c.DestChain = destChain + } +} + +// DoSendRequest similar to TestSendRequest but returns an error. +func DoSendRequest( + t *testing.T, + e deployment.Environment, + state CCIPOnChainState, + opts ...SendReqOpts, +) (*onramp.OnRampCCIPMessageSent, error) { + cfg := &CCIPSendReqConfig{} + for _, opt := range opts { + opt(cfg) + } + // Set default sender if not provided + if cfg.Sender == nil { + cfg.Sender = e.Chains[cfg.SourceChain].DeployerKey + } + t.Logf("Sending CCIP request from chain selector %d to chain selector %d from sender %s", + cfg.SourceChain, cfg.DestChain, cfg.Sender.From.String()) + tx, blockNum, err := CCIPSendRequest(e, state, cfg) + if err != nil { + return nil, err + } + + it, err := state.Chains[cfg.SourceChain].OnRamp.FilterCCIPMessageSent(&bind.FilterOpts{ Start: blockNum, End: &blockNum, Context: context.Background(), - }, []uint64{dest}, []uint64{}) - require.NoError(t, err) + }, []uint64{cfg.DestChain}, []uint64{}) + if err != nil { + return nil, err + } + require.True(t, it.Next()) t.Logf("CCIP message (id %x) sent from chain selector %d to chain selector %d tx %s seqNum %d nonce %d sender %s", it.Event.Message.Header.MessageId[:], - src, - dest, + cfg.SourceChain, + cfg.DestChain, tx.Hash().String(), it.Event.SequenceNumber, it.Event.Message.Header.Nonce, it.Event.Message.Sender.String(), ) - return it.Event + return it.Event, nil } // MakeEVMExtraArgsV2 creates the extra args for the EVM2Any message that is destined @@ -535,6 +623,16 @@ func MakeEVMExtraArgsV2(gasLimit uint64, allowOOO bool) []byte { return extraArgs } +func AddLaneWithDefaultPricesAndFeeQuoterConfig(e deployment.Environment, state CCIPOnChainState, from, to uint64, isTestRouter bool) error { + cfg := LaneConfig{ + SourceSelector: from, + DestSelector: to, + InitialPricesBySource: DefaultInitialPrices, + FeeQuoterDestChain: DefaultFeeQuoterDestChainConfig(), + } + return addLane(e, state, cfg, isTestRouter) +} + // AddLanesForAll adds densely connected lanes for all chains in the environment so that each chain // is connected to every other chain except itself. func AddLanesForAll(e deployment.Environment, state CCIPOnChainState) error { @@ -558,11 +656,11 @@ func ToPackedFee(execFee, daFee *big.Int) *big.Int { const ( // MockLinkAggregatorDescription This is the description of the MockV3Aggregator.sol contract - // nolint:lll + //nolint:lll // https://github.com/smartcontractkit/chainlink/blob/a348b98e90527520049c580000a86fb8ceff7fa7/contracts/src/v0.8/tests/MockV3Aggregator.sol#L76-L76 MockLinkAggregatorDescription = "v0.8/tests/MockV3Aggregator.sol" // MockWETHAggregatorDescription WETH use description from MockETHUSDAggregator.sol - // nolint:lll + //nolint:lll // https://github.com/smartcontractkit/chainlink/blob/a348b98e90527520049c580000a86fb8ceff7fa7/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol#L19-L19 MockWETHAggregatorDescription = "MockETHUSDAggregator" ) @@ -687,7 +785,7 @@ func ConfirmRequestOnSourceAndDest(t *testing.T, env deployment.Environment, sta commonutils.JustError(ConfirmCommitWithExpectedSeqNumRange(t, env.Chains[sourceCS], env.Chains[destCS], state.Chains[destCS].OffRamp, &startBlock, cciptypes.SeqNumRange{ cciptypes.SeqNum(msgSentEvent.SequenceNumber), cciptypes.SeqNum(msgSentEvent.SequenceNumber), - }))) + }, true))) fmt.Printf("Commit confirmed for seqnr %d", msgSentEvent.SequenceNumber) require.NoError( @@ -740,63 +838,102 @@ func DeployTransferableToken( lggr logger.Logger, chains map[uint64]deployment.Chain, src, dst uint64, + srcActor, dstActor *bind.TransactOpts, state CCIPOnChainState, addresses deployment.AddressBook, token string, ) (*burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, *burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, error) { // Deploy token and pools - srcToken, srcPool, err := deployTransferTokenOneEnd(lggr, chains[src], addresses, token) + srcToken, srcPool, dstToken, dstPool, err := deployTokenPoolsInParallel(lggr, chains, src, dst, srcActor, dstActor, state, addresses, token) if err != nil { return nil, nil, nil, nil, err } - dstToken, dstPool, err := deployTransferTokenOneEnd(lggr, chains[dst], addresses, token) - if err != nil { - return nil, nil, nil, nil, err - } - - // Attach token pools to registry - if err := attachTokenToTheRegistry(chains[src], state.Chains[src], chains[src].DeployerKey, srcToken.Address(), srcPool.Address()); err != nil { - return nil, nil, nil, nil, err - } - - if err := attachTokenToTheRegistry(chains[dst], state.Chains[dst], chains[dst].DeployerKey, dstToken.Address(), dstPool.Address()); err != nil { - return nil, nil, nil, nil, err - } - - // Connect pool to each other - if err := setTokenPoolCounterPart(chains[src], srcPool, dst, dstToken.Address(), dstPool.Address()); err != nil { - return nil, nil, nil, nil, err - } - if err := setTokenPoolCounterPart(chains[dst], dstPool, src, srcToken.Address(), srcPool.Address()); err != nil { + // Configure pools in parallel + configurePoolGrp := errgroup.Group{} + configurePoolGrp.Go(func() error { + err := setTokenPoolCounterPart(chains[src], srcPool, srcActor, dst, dstToken.Address(), dstPool.Address()) + if err != nil { + return fmt.Errorf("failed to set token pool counter part chain %d: %w", src, err) + } + err = grantMintBurnPermissions(lggr, chains[src], srcToken, srcActor, srcPool.Address()) + if err != nil { + return fmt.Errorf("failed to grant mint burn permissions chain %d: %w", src, err) + } + return nil + }) + configurePoolGrp.Go(func() error { + err := setTokenPoolCounterPart(chains[dst], dstPool, dstActor, src, srcToken.Address(), srcPool.Address()) + if err != nil { + return fmt.Errorf("failed to set token pool counter part chain %d: %w", dst, err) + } + if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, dstActor, dstPool.Address()); err != nil { + return fmt.Errorf("failed to grant mint burn permissions chain %d: %w", dst, err) + } + return nil + }) + if err := configurePoolGrp.Wait(); err != nil { return nil, nil, nil, nil, err } + return srcToken, srcPool, dstToken, dstPool, nil +} - // Add burn/mint permissions - if err := grantMintBurnPermissions(lggr, chains[src], srcToken, srcPool.Address()); err != nil { +func deployTokenPoolsInParallel( + lggr logger.Logger, + chains map[uint64]deployment.Chain, + src, dst uint64, + srcActor, dstActor *bind.TransactOpts, + state CCIPOnChainState, + addresses deployment.AddressBook, + token string, +) ( + *burn_mint_erc677.BurnMintERC677, + *burn_mint_token_pool.BurnMintTokenPool, + *burn_mint_erc677.BurnMintERC677, + *burn_mint_token_pool.BurnMintTokenPool, + error, +) { + deployGrp := errgroup.Group{} + // Deploy token and pools + var srcToken *burn_mint_erc677.BurnMintERC677 + var srcPool *burn_mint_token_pool.BurnMintTokenPool + var dstToken *burn_mint_erc677.BurnMintERC677 + var dstPool *burn_mint_token_pool.BurnMintTokenPool + + deployGrp.Go(func() error { + var err error + srcToken, srcPool, err = deployTransferTokenOneEnd(lggr, chains[src], srcActor, addresses, token) + if err != nil { + return err + } + if err := attachTokenToTheRegistry(chains[src], state.Chains[src], srcActor, srcToken.Address(), srcPool.Address()); err != nil { + return err + } + return nil + }) + deployGrp.Go(func() error { + var err error + dstToken, dstPool, err = deployTransferTokenOneEnd(lggr, chains[dst], dstActor, addresses, token) + if err != nil { + return err + } + if err := attachTokenToTheRegistry(chains[dst], state.Chains[dst], dstActor, dstToken.Address(), dstPool.Address()); err != nil { + return err + } + return nil + }) + if err := deployGrp.Wait(); err != nil { return nil, nil, nil, nil, err } - - if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, dstPool.Address()); err != nil { - return nil, nil, nil, nil, err + if srcToken == nil || srcPool == nil || dstToken == nil || dstPool == nil { + return nil, nil, nil, nil, fmt.Errorf("failed to deploy token and pool") } - return srcToken, srcPool, dstToken, dstPool, nil } -func grantMintBurnPermissions(lggr logger.Logger, chain deployment.Chain, token *burn_mint_erc677.BurnMintERC677, address common.Address) error { - lggr.Infow("Granting burn permissions", "token", token.Address(), "burner", address) - tx, err := token.GrantBurnRole(chain.DeployerKey, address) - if err != nil { - return err - } - _, err = chain.Confirm(tx) - if err != nil { - return err - } - - lggr.Infow("Granting mint permissions", "token", token.Address(), "minter", address) - tx, err = token.GrantMintRole(chain.DeployerKey, address) +func grantMintBurnPermissions(lggr logger.Logger, chain deployment.Chain, token *burn_mint_erc677.BurnMintERC677, actor *bind.TransactOpts, address common.Address) error { + lggr.Infow("Granting burn/mint permissions", "token", token.Address(), "address", address) + tx, err := token.GrantMintAndBurnRoles(actor, address) if err != nil { return err } @@ -808,6 +945,7 @@ func setUSDCTokenPoolCounterPart( chain deployment.Chain, tokenPool *usdc_token_pool.USDCTokenPool, destChainSelector uint64, + actor *bind.TransactOpts, destTokenAddress common.Address, destTokenPoolAddress common.Address, ) error { @@ -840,18 +978,12 @@ func setUSDCTokenPoolCounterPart( return err } - return setTokenPoolCounterPart(chain, pool, destChainSelector, destTokenAddress, destTokenPoolAddress) + return setTokenPoolCounterPart(chain, pool, actor, destChainSelector, destTokenAddress, destTokenPoolAddress) } -func setTokenPoolCounterPart( - chain deployment.Chain, - tokenPool *burn_mint_token_pool.BurnMintTokenPool, - destChainSelector uint64, - destTokenAddress common.Address, - destTokenPoolAddress common.Address, -) error { +func setTokenPoolCounterPart(chain deployment.Chain, tokenPool *burn_mint_token_pool.BurnMintTokenPool, actor *bind.TransactOpts, destChainSelector uint64, destTokenAddress common.Address, destTokenPoolAddress common.Address) error { tx, err := tokenPool.ApplyChainUpdates( - chain.DeployerKey, + actor, []uint64{}, []burn_mint_token_pool.TokenPoolChainUpdate{ { @@ -881,7 +1013,7 @@ func setTokenPoolCounterPart( } tx, err = tokenPool.AddRemotePool( - chain.DeployerKey, + actor, destChainSelector, destTokenPoolAddress.Bytes(), ) @@ -941,6 +1073,7 @@ func attachTokenToTheRegistry( func deployTransferTokenOneEnd( lggr logger.Logger, chain deployment.Chain, + deployer *bind.TransactOpts, addressBook deployment.AddressBook, tokenSymbol string, ) (*burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, error) { @@ -965,8 +1098,8 @@ func deployTransferTokenOneEnd( tokenContract, err := deployment.DeployContract(lggr, chain, addressBook, func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { - USDCTokenAddr, tx, token, err2 := burn_mint_erc677.DeployBurnMintERC677( - chain.DeployerKey, + tokenAddress, tx, token, err2 := burn_mint_erc677.DeployBurnMintERC677( + deployer, chain.Client, tokenSymbol, tokenSymbol, @@ -974,7 +1107,7 @@ func deployTransferTokenOneEnd( big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), ) return deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ - USDCTokenAddr, token, tx, deployment.NewTypeAndVersion(BurnMintToken, deployment.Version1_0_0), err2, + tokenAddress, token, tx, deployment.NewTypeAndVersion(BurnMintToken, deployment.Version1_0_0), err2, } }) if err != nil { @@ -982,7 +1115,7 @@ func deployTransferTokenOneEnd( return nil, nil, err } - tx, err := tokenContract.Contract.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) + tx, err := tokenContract.Contract.GrantMintRole(deployer, deployer.From) if err != nil { return nil, nil, err } @@ -994,7 +1127,7 @@ func deployTransferTokenOneEnd( tokenPool, err := deployment.DeployContract(lggr, chain, addressBook, func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_token_pool.BurnMintTokenPool] { tokenPoolAddress, tx, tokenPoolContract, err2 := burn_mint_token_pool.DeployBurnMintTokenPool( - chain.DeployerKey, + deployer, chain.Client, tokenContract.Address, tokenDecimals, @@ -1003,7 +1136,7 @@ func deployTransferTokenOneEnd( common.HexToAddress(routerAddress), ) return deployment.ContractDeploy[*burn_mint_token_pool.BurnMintTokenPool]{ - tokenPoolAddress, tokenPoolContract, tx, deployment.NewTypeAndVersion(BurnMintTokenPool, deployment.Version1_0_0), err2, + tokenPoolAddress, tokenPoolContract, tx, deployment.NewTypeAndVersion(BurnMintTokenPool, deployment.Version1_5_1), err2, } }) if err != nil { @@ -1013,3 +1146,304 @@ func deployTransferTokenOneEnd( return tokenContract.Contract, tokenPool.Contract, nil } + +type MintTokenInfo struct { + auth *bind.TransactOpts + sender *bind.TransactOpts + tokens []*burn_mint_erc677.BurnMintERC677 +} + +func NewMintTokenInfo(auth *bind.TransactOpts, tokens ...*burn_mint_erc677.BurnMintERC677) MintTokenInfo { + return MintTokenInfo{auth: auth, tokens: tokens} +} + +func NewMintTokenWithCustomSender(auth *bind.TransactOpts, sender *bind.TransactOpts, tokens ...*burn_mint_erc677.BurnMintERC677) MintTokenInfo { + return MintTokenInfo{auth: auth, sender: sender, tokens: tokens} +} + +// MintAndAllow mints tokens for deployers and allow router to spend them +func MintAndAllow( + t *testing.T, + e deployment.Environment, + state CCIPOnChainState, + tokenMap map[uint64][]MintTokenInfo, +) { + configurePoolGrp := errgroup.Group{} + tenCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(10)) + + for chain, mintTokenInfos := range tokenMap { + mintTokenInfos := mintTokenInfos + + configurePoolGrp.Go(func() error { + for _, mintTokenInfo := range mintTokenInfos { + sender := mintTokenInfo.sender + if sender == nil { + sender = e.Chains[chain].DeployerKey + } + + for _, token := range mintTokenInfo.tokens { + tx, err := token.Mint( + mintTokenInfo.auth, + sender.From, + new(big.Int).Mul(tenCoins, big.NewInt(10)), + ) + require.NoError(t, err) + _, err = e.Chains[chain].Confirm(tx) + require.NoError(t, err) + + tx, err = token.Approve(sender, state.Chains[chain].Router.Address(), tenCoins) + require.NoError(t, err) + _, err = e.Chains[chain].Confirm(tx) + require.NoError(t, err) + } + } + return nil + }) + } + + require.NoError(t, configurePoolGrp.Wait()) +} + +func Transfer( + ctx context.Context, + t *testing.T, + env deployment.Environment, + state CCIPOnChainState, + sourceChain, destChain uint64, + tokens []router.ClientEVMTokenAmount, + receiver common.Address, + data, extraArgs []byte, +) (*onramp.OnRampCCIPMessageSent, map[uint64]*uint64) { + startBlocks := make(map[uint64]*uint64) + + latesthdr, err := env.Chains[destChain].Client.HeaderByNumber(ctx, nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + startBlocks[destChain] = &block + + msgSentEvent := TestSendRequest(t, env, state, sourceChain, destChain, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(receiver.Bytes(), 32), + Data: data, + TokenAmounts: tokens, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: extraArgs, + }) + return msgSentEvent, startBlocks +} + +type TestTransferRequest struct { + Name string + SourceChain, DestChain uint64 + Receiver common.Address + ExpectedStatus int + // optional + Tokens []router.ClientEVMTokenAmount + Data []byte + ExtraArgs []byte + ExpectedTokenBalances map[common.Address]*big.Int +} + +// TransferMultiple sends multiple CCIPMessages (represented as TestTransferRequest) sequentially. +// It verifies whether message is not reverted on the source and proper event is emitted by OnRamp. +// However, it doesn't wait for message to be committed or executed. Therefore, you can send multiple messages very fast, +// but you need to make sure they are committed/executed on your own (if that's the intention). +// It saves some time during test execution, because we let plugins batch instead of executing one by one +// If you want to wait for execution in a "batch" manner you will need to pass maps returned by TransferMultiple to +// either ConfirmMultipleCommits (for commit) or ConfirmExecWithSeqNrsForAll (for exec). Check example usage in the tests. +func TransferMultiple( + ctx context.Context, + t *testing.T, + env deployment.Environment, + state CCIPOnChainState, + requests []TestTransferRequest, +) ( + map[uint64]*uint64, + map[SourceDestPair]cciptypes.SeqNumRange, + map[SourceDestPair]map[uint64]int, + map[uint64]map[TokenReceiverIdentifier]*big.Int, +) { + startBlocks := make(map[uint64]*uint64) + expectedSeqNums := make(map[SourceDestPair]cciptypes.SeqNumRange) + expectedExecutionStates := make(map[SourceDestPair]map[uint64]int) + expectedTokenBalances := make(TokenBalanceAccumulator) + + for _, tt := range requests { + t.Run(tt.Name, func(t *testing.T) { + expectedTokenBalances.add(tt.DestChain, tt.Receiver, tt.ExpectedTokenBalances) + + pairId := SourceDestPair{ + SourceChainSelector: tt.SourceChain, + DestChainSelector: tt.DestChain, + } + + msg, blocks := Transfer( + ctx, t, env, state, tt.SourceChain, tt.DestChain, tt.Tokens, tt.Receiver, tt.Data, tt.ExtraArgs) + if _, ok := expectedExecutionStates[pairId]; !ok { + expectedExecutionStates[pairId] = make(map[uint64]int) + } + expectedExecutionStates[pairId][msg.SequenceNumber] = tt.ExpectedStatus + + if _, ok := startBlocks[tt.DestChain]; !ok { + startBlocks[tt.DestChain] = blocks[tt.DestChain] + } + + seqNr, ok := expectedSeqNums[pairId] + if ok { + expectedSeqNums[pairId] = cciptypes.NewSeqNumRange( + seqNr.Start(), cciptypes.SeqNum(msg.SequenceNumber), + ) + } else { + expectedSeqNums[pairId] = cciptypes.NewSeqNumRange( + cciptypes.SeqNum(msg.SequenceNumber), cciptypes.SeqNum(msg.SequenceNumber), + ) + } + }) + } + + return startBlocks, expectedSeqNums, expectedExecutionStates, expectedTokenBalances +} + +// TransferAndWaitForSuccess sends a message from sourceChain to destChain and waits for it to be executed +func TransferAndWaitForSuccess( + ctx context.Context, + t *testing.T, + env deployment.Environment, + state CCIPOnChainState, + sourceChain, destChain uint64, + tokens []router.ClientEVMTokenAmount, + receiver common.Address, + data []byte, + expectedStatus int, + extraArgs []byte, +) { + identifier := SourceDestPair{ + SourceChainSelector: sourceChain, + DestChainSelector: destChain, + } + + expectedSeqNum := make(map[SourceDestPair]uint64) + expectedSeqNumExec := make(map[SourceDestPair][]uint64) + + msgSentEvent, startBlocks := Transfer(ctx, t, env, state, sourceChain, destChain, tokens, receiver, data, extraArgs) + expectedSeqNum[identifier] = msgSentEvent.SequenceNumber + expectedSeqNumExec[identifier] = []uint64{msgSentEvent.SequenceNumber} + + // Wait for all commit reports to land. + ConfirmCommitForAllWithExpectedSeqNums(t, env, state, expectedSeqNum, startBlocks) + + // Wait for all exec reports to land + states := ConfirmExecWithSeqNrsForAll(t, env, state, expectedSeqNumExec, startBlocks) + require.Equal(t, expectedStatus, states[identifier][msgSentEvent.SequenceNumber]) +} + +// TokenBalanceAccumulator is a convenient accumulator to aggregate expected balances of different tokens +// used across the tests. You can iterate over your test cases and build the final "expected" balances for tokens (per chain, per sender) +// For instance, if your test runs multiple transfers for the same token, and you want to verify the balance of tokens at +// the end of the execution, you can simply use that struct for aggregating expected tokens +// Please also see WaitForTokenBalances to better understand how you can assert token balances +type TokenBalanceAccumulator map[uint64]map[TokenReceiverIdentifier]*big.Int + +func (t TokenBalanceAccumulator) add( + destChain uint64, + receiver common.Address, + expectedBalance map[common.Address]*big.Int) { + for token, balance := range expectedBalance { + tkIdentifier := TokenReceiverIdentifier{token, receiver} + + if _, ok := t[destChain]; !ok { + t[destChain] = make(map[TokenReceiverIdentifier]*big.Int) + } + actual, ok := t[destChain][tkIdentifier] + if !ok { + actual = big.NewInt(0) + } + t[destChain][tkIdentifier] = new(big.Int).Add(actual, balance) + } +} + +type TokenReceiverIdentifier struct { + token common.Address + receiver common.Address +} + +// WaitForTokenBalances waits for multiple ERC20 tokens to reach a particular balance +// It works in a batch manner, so you can pass and exhaustive list of different tokens (per senders and chains) +// and it would work concurrently for the balance to be met. Check WaitForTheTokenBalance to see how balance +// checking is made for a token/receiver pair +func WaitForTokenBalances( + ctx context.Context, + t *testing.T, + chains map[uint64]deployment.Chain, + expectedBalances map[uint64]map[TokenReceiverIdentifier]*big.Int, +) { + errGrp := &errgroup.Group{} + for chainID, tokens := range expectedBalances { + for id, balance := range tokens { + id := id + balance := balance + errGrp.Go(func() error { + WaitForTheTokenBalance(ctx, t, id.token, id.receiver, chains[chainID], balance) + return nil + }) + } + } + require.NoError(t, errGrp.Wait()) +} + +func WaitForTheTokenBalance( + ctx context.Context, + t *testing.T, + token common.Address, + receiver common.Address, + chain deployment.Chain, + expected *big.Int, +) { + tokenContract, err := burn_mint_erc677.NewBurnMintERC677(token, chain.Client) + require.NoError(t, err) + + require.Eventually(t, func() bool { + actualBalance, err := tokenContract.BalanceOf(&bind.CallOpts{Context: ctx}, receiver) + require.NoError(t, err) + + t.Log("Waiting for the token balance", + "expected", expected, + "actual", actualBalance, + "token", token, + "receiver", receiver, + ) + + return actualBalance.Cmp(expected) == 0 + }, tests.WaitTimeout(t), 100*time.Millisecond) +} + +func GetTokenBalance( + ctx context.Context, + t *testing.T, + token common.Address, + receiver common.Address, + chain deployment.Chain, +) *big.Int { + tokenContract, err := burn_mint_erc677.NewBurnMintERC677(token, chain.Client) + require.NoError(t, err) + + balance, err := tokenContract.BalanceOf(&bind.CallOpts{Context: ctx}, receiver) + require.NoError(t, err) + + t.Log("Getting token balance", + "actual", balance, + "token", token, + "receiver", receiver, + ) + + return balance +} + +func DefaultRouterMessage(receiverAddress common.Address) router.ClientEVM2AnyMessage { + return router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(receiverAddress.Bytes(), 32), + Data: []byte("hello world"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + } +} diff --git a/deployment/ccip/changeset/test_usdc_helpers.go b/deployment/ccip/changeset/test_usdc_helpers.go index 4a39f4e7ba1..55f1bd25a36 100644 --- a/deployment/ccip/changeset/test_usdc_helpers.go +++ b/deployment/ccip/changeset/test_usdc_helpers.go @@ -3,6 +3,8 @@ package changeset import ( "math/big" + "golang.org/x/sync/errgroup" + "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink-ccip/pkg/reader" @@ -27,53 +29,78 @@ func ConfigureUSDCTokenPools( srcPool := state.Chains[src].USDCTokenPool dstPool := state.Chains[dst].USDCTokenPool - // Attach token pools to registry - if err := attachTokenToTheRegistry(chains[src], state.Chains[src], chains[src].DeployerKey, srcToken.Address(), srcPool.Address()); err != nil { - lggr.Errorw("Failed to attach token to the registry", "err", err, "token", srcToken.Address(), "pool", srcPool.Address()) - return nil, nil, err + args := []struct { + sourceChain deployment.Chain + dstChainSel uint64 + state CCIPChainState + srcToken *burn_mint_erc677.BurnMintERC677 + srcPool *usdc_token_pool.USDCTokenPool + dstToken *burn_mint_erc677.BurnMintERC677 + dstPool *usdc_token_pool.USDCTokenPool + }{ + { + chains[src], + dst, + state.Chains[src], + srcToken, + srcPool, + dstToken, + dstPool, + }, + { + chains[dst], + src, + state.Chains[dst], + dstToken, + dstPool, + srcToken, + srcPool, + }, } - if err := attachTokenToTheRegistry(chains[dst], state.Chains[dst], chains[dst].DeployerKey, dstToken.Address(), dstPool.Address()); err != nil { - lggr.Errorw("Failed to attach token to the registry", "err", err, "token", dstToken.Address(), "pool", dstPool.Address()) - return nil, nil, err + configurePoolGrp := errgroup.Group{} + for _, arg := range args { + configurePoolGrp.Go(configureSingleChain(lggr, arg.sourceChain, arg.dstChainSel, arg.state, arg.srcToken, arg.srcPool, arg.dstToken, arg.dstPool)) } - - // Connect pool to each other - if err := setUSDCTokenPoolCounterPart(chains[src], srcPool, dst, dstToken.Address(), dstPool.Address()); err != nil { - lggr.Errorw("Failed to set counter part", "err", err, "srcPool", srcPool.Address(), "dstPool", dstPool.Address()) + if err := configurePoolGrp.Wait(); err != nil { return nil, nil, err } + return srcToken, dstToken, nil +} - if err := setUSDCTokenPoolCounterPart(chains[dst], dstPool, src, srcToken.Address(), srcPool.Address()); err != nil { - lggr.Errorw("Failed to set counter part", "err", err, "srcPool", dstPool.Address(), "dstPool", srcPool.Address()) - return nil, nil, err - } +func configureSingleChain( + lggr logger.Logger, + sourceChain deployment.Chain, + dstChainSel uint64, + state CCIPChainState, + srcToken *burn_mint_erc677.BurnMintERC677, + srcPool *usdc_token_pool.USDCTokenPool, + dstToken *burn_mint_erc677.BurnMintERC677, + dstPool *usdc_token_pool.USDCTokenPool, +) func() error { + return func() error { + if err := attachTokenToTheRegistry(sourceChain, state, sourceChain.DeployerKey, srcToken.Address(), srcPool.Address()); err != nil { + lggr.Errorw("Failed to attach token to the registry", "err", err, "token", srcToken.Address(), "pool", srcPool.Address()) + return err + } - // Add burn/mint permissions for source - for _, addr := range []common.Address{ - srcPool.Address(), - state.Chains[src].MockUSDCTokenMessenger.Address(), - state.Chains[src].MockUSDCTransmitter.Address(), - } { - if err := grantMintBurnPermissions(lggr, chains[src], srcToken, addr); err != nil { - lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", srcToken.Address(), "minter", addr) - return nil, nil, err + if err := setUSDCTokenPoolCounterPart(sourceChain, srcPool, dstChainSel, sourceChain.DeployerKey, dstToken.Address(), dstPool.Address()); err != nil { + lggr.Errorw("Failed to set counter part", "err", err, "srcPool", srcPool.Address(), "dstPool", dstPool.Address()) + return err } - } - // Add burn/mint permissions for dest - for _, addr := range []common.Address{ - dstPool.Address(), - state.Chains[dst].MockUSDCTokenMessenger.Address(), - state.Chains[dst].MockUSDCTransmitter.Address(), - } { - if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, addr); err != nil { - lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", dstToken.Address(), "minter", addr) - return nil, nil, err + for _, addr := range []common.Address{ + srcPool.Address(), + state.MockUSDCTokenMessenger.Address(), + state.MockUSDCTransmitter.Address(), + } { + if err := grantMintBurnPermissions(lggr, sourceChain, srcToken, sourceChain.DeployerKey, addr); err != nil { + lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", srcToken.Address(), "address", addr) + return err + } } + return nil } - - return srcToken, dstToken, nil } func UpdateFeeQuoterForUSDC( @@ -134,10 +161,10 @@ func DeployUSDC( tokenAddress, tx, tokenContract, err2 := burn_mint_erc677.DeployBurnMintERC677( chain.DeployerKey, chain.Client, - "USDC Token", - "USDC", - uint8(18), - big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), + USDCName, + string(USDCSymbol), + UsdcDecimals, + big.NewInt(0), ) return deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ Address: tokenAddress, @@ -148,13 +175,13 @@ func DeployUSDC( } }) if err != nil { - lggr.Errorw("Failed to deploy USDC token", "err", err) + lggr.Errorw("Failed to deploy USDC token", "chain", chain.String(), "err", err) return nil, nil, nil, nil, err } tx, err := token.Contract.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) if err != nil { - lggr.Errorw("Failed to grant mint role", "token", token.Contract.Address(), "err", err) + lggr.Errorw("Failed to grant mint role", "chain", chain.String(), "token", token.Contract.Address(), "err", err) return nil, nil, nil, nil, err } _, err = chain.Confirm(tx) @@ -180,12 +207,10 @@ func DeployUSDC( } }) if err != nil { - lggr.Errorw("Failed to deploy mock USDC transmitter", "err", err) + lggr.Errorw("Failed to deploy mock USDC transmitter", "chain", chain.String(), "err", err) return nil, nil, nil, nil, err } - lggr.Infow("deployed mock USDC transmitter", "addr", transmitter.Address) - messenger, err := deployment.DeployContract(lggr, chain, addresses, func(chain deployment.Chain) deployment.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger] { messengerAddress, tx, messengerContract, err2 := mock_usdc_token_messenger.DeployMockE2EUSDCTokenMessenger( @@ -203,10 +228,9 @@ func DeployUSDC( } }) if err != nil { - lggr.Errorw("Failed to deploy USDC token messenger", "err", err) + lggr.Errorw("Failed to deploy USDC token messenger", "chain", chain.String(), "err", err) return nil, nil, nil, nil, err } - lggr.Infow("deployed mock USDC token messenger", "addr", messenger.Address) tokenPool, err := deployment.DeployContract(lggr, chain, addresses, func(chain deployment.Chain) deployment.ContractDeploy[*usdc_token_pool.USDCTokenPool] { @@ -228,10 +252,9 @@ func DeployUSDC( } }) if err != nil { - lggr.Errorw("Failed to deploy USDC token pool", "err", err) + lggr.Errorw("Failed to deploy USDC token pool", "chain", chain.String(), "err", err) return nil, nil, nil, nil, err } - lggr.Infow("deployed USDC token pool", "addr", tokenPool.Address) return token.Contract, tokenPool.Contract, messenger.Contract, transmitter.Contract, nil } diff --git a/deployment/ccip/changeset/token_info.go b/deployment/ccip/changeset/token_info.go index e9657544a01..7c008a8a884 100644 --- a/deployment/ccip/changeset/token_info.go +++ b/deployment/ccip/changeset/token_info.go @@ -3,12 +3,23 @@ package changeset import ( "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" +) - "github.com/smartcontractkit/chainlink-common/pkg/logger" +type TokenSymbol string + +const ( + LinkSymbol TokenSymbol = "LINK" + WethSymbol TokenSymbol = "WETH" + USDCSymbol TokenSymbol = "USDC" + USDCName string = "USD Coin" + LinkDecimals = 18 + WethDecimals = 18 + UsdcDecimals = 6 ) var ( @@ -56,7 +67,7 @@ func (tc *TokenConfig) UpsertTokenInfo( // GetTokenInfo Adds mapping between dest chain tokens and their respective aggregators on feed chain. func (tc *TokenConfig) GetTokenInfo( lggr logger.Logger, - linkToken *burn_mint_erc677.BurnMintERC677, + linkToken *link_token.LinkToken, wethToken *weth9.WETH9, ) map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo { tokenToAggregate := make(map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo) diff --git a/deployment/ccip/changeset/view_test.go b/deployment/ccip/changeset/view_test.go new file mode 100644 index 00000000000..934b937f7b5 --- /dev/null +++ b/deployment/ccip/changeset/view_test.go @@ -0,0 +1,22 @@ +package changeset + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestSmokeView(t *testing.T) { + lggr := logger.TestLogger(t) + tenv := NewMemoryEnvironmentWithJobsAndContracts(t, lggr, memory.MemoryEnvironmentConfig{ + Chains: 3, + Nodes: 4, + Bootstraps: 1, + NumOfUsersPerChain: 1, + }, nil) + _, err := ViewCCIP(tenv.Env) + require.NoError(t, err) +} diff --git a/deployment/ccip/view/view.go b/deployment/ccip/view/view.go index 318e09100b9..1cacd58cc2b 100644 --- a/deployment/ccip/view/view.go +++ b/deployment/ccip/view/view.go @@ -27,6 +27,8 @@ type ChainView struct { OffRamp map[string]v1_6.OffRampView `json:"offRamp,omitempty"` CapabilityRegistry map[string]common_v1_0.CapabilityRegistryView `json:"capabilityRegistry,omitempty"` MCMSWithTimelock common_v1_0.MCMSWithTimelockView `json:"mcmsWithTimelock,omitempty"` + LinkToken common_v1_0.LinkTokenView `json:"linkToken,omitempty"` + StaticLinkToken common_v1_0.StaticLinkTokenView `json:"staticLinkToken,omitempty"` } func NewChain() ChainView { diff --git a/deployment/common/changeset/deploy_link_token.go b/deployment/common/changeset/deploy_link_token.go index 5f88b410f67..292c07c93df 100644 --- a/deployment/common/changeset/deploy_link_token.go +++ b/deployment/common/changeset/deploy_link_token.go @@ -10,20 +10,24 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" ) -var _ deployment.ChangeSet[uint64] = DeployLinkToken +var _ deployment.ChangeSet[[]uint64] = DeployLinkToken // DeployLinkToken deploys a link token contract to the chain identified by the chainSelector. -func DeployLinkToken(e deployment.Environment, chainSelector uint64) (deployment.ChangesetOutput, error) { - c, ok := e.Chains[chainSelector] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") +func DeployLinkToken(e deployment.Environment, chains []uint64) (deployment.ChangesetOutput, error) { + for _, chain := range chains { + _, ok := e.Chains[chain] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") + } } newAddresses := deployment.NewMemoryAddressBook() - _, err := deployLinkTokenContract( - e.Logger, c, newAddresses, - ) - if err != nil { - return deployment.ChangesetOutput{AddressBook: newAddresses}, err + for _, chain := range chains { + _, err := deployLinkTokenContract( + e.Logger, e.Chains[chain], newAddresses, + ) + if err != nil { + return deployment.ChangesetOutput{AddressBook: newAddresses}, err + } } return deployment.ChangesetOutput{AddressBook: newAddresses}, nil } @@ -48,7 +52,7 @@ func deployLinkTokenContract( } }) if err != nil { - lggr.Errorw("Failed to deploy link token", "err", err) + lggr.Errorw("Failed to deploy link token", "chain", chain.String(), "err", err) return linkToken, err } return linkToken, nil diff --git a/deployment/common/changeset/deploy_link_token_test.go b/deployment/common/changeset/deploy_link_token_test.go index a18e0181623..a61743e9bf4 100644 --- a/deployment/common/changeset/deploy_link_token_test.go +++ b/deployment/common/changeset/deploy_link_token_test.go @@ -3,37 +3,33 @@ package changeset_test import ( "testing" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) func TestDeployLinkToken(t *testing.T) { t.Parallel() - - lggr := logger.Test(t) - cfg := memory.MemoryEnvironmentConfig{ - Nodes: 1, - Chains: 2, - } - env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) - chainSelector := env.AllChainSelectors()[0] - - resp, err := changeset.DeployLinkToken(env, chainSelector) + lggr := logger.TestLogger(t) + e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + Chains: 1, + }) + chain1 := e.AllChainSelectors()[0] + e, err := changeset.ApplyChangesets(t, e, nil, []changeset.ChangesetApplication{ + { + Changeset: changeset.WrapChangeSet(changeset.DeployLinkToken), + Config: []uint64{chain1}, + }, + }) require.NoError(t, err) - require.NotNil(t, resp) - - // LinkToken should be deployed on chain 0 - addrs, err := resp.AddressBook.AddressesForChain(chainSelector) + addrs, err := e.ExistingAddresses.AddressesForChain(chain1) + require.NoError(t, err) + state, err := changeset.MaybeLoadLinkTokenState(e.Chains[chain1], addrs) + require.NoError(t, err) + // View itself already unit tested + _, err = state.GenerateLinkView() require.NoError(t, err) - require.Len(t, addrs, 1) - - // nothing on chain 1 - require.NotEqual(t, chainSelector, env.AllChainSelectors()[1]) - oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) - assert.Len(t, oaddrs, 0) } diff --git a/deployment/common/changeset/internal/mcms.go b/deployment/common/changeset/internal/mcms.go index 1e2fb958aae..281f43924f4 100644 --- a/deployment/common/changeset/internal/mcms.go +++ b/deployment/common/changeset/internal/mcms.go @@ -6,6 +6,7 @@ import ( owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" @@ -30,7 +31,7 @@ func DeployMCMSWithConfig( } }) if err != nil { - lggr.Errorw("Failed to deploy mcm", "err", err) + lggr.Errorw("Failed to deploy mcm", "chain", chain.String(), "err", err) return mcm, err } mcmsTx, err := mcm.Contract.SetConfig(chain.DeployerKey, @@ -42,7 +43,7 @@ func DeployMCMSWithConfig( false, ) if _, err := deployment.ConfirmIfNoError(chain, mcmsTx, err); err != nil { - lggr.Errorw("Failed to confirm mcm config", "err", err) + lggr.Errorw("Failed to confirm mcm config", "chain", chain.String(), "err", err) return mcm, err } return mcm, nil @@ -95,7 +96,7 @@ func DeployMCMSWithTimelockContracts( return nil, err } - timelock, err := deployment.DeployContract[*owner_helpers.RBACTimelock](lggr, chain, ab, + timelock, err := deployment.DeployContract(lggr, chain, ab, func(chain deployment.Chain) deployment.ContractDeploy[*owner_helpers.RBACTimelock] { timelock, tx2, cc, err2 := owner_helpers.DeployRBACTimelock( chain.DeployerKey, @@ -115,15 +116,14 @@ func DeployMCMSWithTimelockContracts( } }) if err != nil { - lggr.Errorw("Failed to deploy timelock", "err", err) + lggr.Errorw("Failed to deploy timelock", "chain", chain.String(), "err", err) return nil, err } - lggr.Infow("deployed timelock", "addr", timelock.Address) // We grant the timelock the admin role on the MCMS contracts. tx, err := timelock.Contract.GrantRole(chain.DeployerKey, v1_0.ADMIN_ROLE.ID, timelock.Address) if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to grant timelock admin role", "err", err) + lggr.Errorw("Failed to grant timelock admin role", "chain", chain.String(), "err", err) return nil, err } // After the proposer cycle is validated, diff --git a/deployment/common/changeset/internal/mcms_test.go b/deployment/common/changeset/internal/mcms_test.go index 9969a0e5bc9..2269911f4cd 100644 --- a/deployment/common/changeset/internal/mcms_test.go +++ b/deployment/common/changeset/internal/mcms_test.go @@ -49,7 +49,7 @@ func TestDeployMCMSWithTimelockContracts(t *testing.T) { addresses, err := ab.AddressesForChain(chainsel.TEST_90000001.Selector) require.NoError(t, err) require.Len(t, addresses, 4) - mcmsState, err := changeset.LoadMCMSWithTimelockState(chains[chainsel.TEST_90000001.Selector], addresses) + mcmsState, err := changeset.MaybeLoadMCMSWithTimelockState(chains[chainsel.TEST_90000001.Selector], addresses) require.NoError(t, err) v, err := mcmsState.GenerateMCMSWithTimelockView() b, err := json.MarshalIndent(v, "", " ") diff --git a/deployment/common/changeset/state.go b/deployment/common/changeset/state.go index 38a1d02c044..0055c908f8d 100644 --- a/deployment/common/changeset/state.go +++ b/deployment/common/changeset/state.go @@ -2,6 +2,7 @@ package changeset import ( "errors" + "fmt" "github.com/ethereum/go-ethereum/common" owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" @@ -9,11 +10,14 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" ) // MCMSWithTimelockState holds the Go bindings // for a MCMSWithTimelock contract deployment. // It is public for use in product specific packages. +// Either all fields are nil or all fields are non-nil. type MCMSWithTimelockState struct { CancellerMcm *owner_helpers.ManyChainMultiSig BypasserMcm *owner_helpers.ManyChainMultiSig @@ -21,6 +25,8 @@ type MCMSWithTimelockState struct { Timelock *owner_helpers.RBACTimelock } +// Validate checks that all fields are non-nil, ensuring it's ready +// for use generating views or interactions. func (state MCMSWithTimelockState) Validate() error { if state.Timelock == nil { return errors.New("timelock not found") @@ -65,29 +71,51 @@ func (state MCMSWithTimelockState) GenerateMCMSWithTimelockView() (v1_0.MCMSWith }, nil } -func LoadMCMSWithTimelockState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*MCMSWithTimelockState, error) { +// MaybeLoadMCMSWithTimelockState looks for the addresses corresponding to +// contracts deployed with DeployMCMSWithTimelock and loads them into a +// MCMSWithTimelockState struct. If none of the contracts are found, the state struct will be nil. +// An error indicates: +// - Found but was unable to load a contract +// - It only found part of the bundle of contracts +// - If found more than one instance of a contract (we expect one bundle in the given addresses) +func MaybeLoadMCMSWithTimelockState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*MCMSWithTimelockState, error) { state := MCMSWithTimelockState{} + // We expect one of each contract on the chain. + timelock := deployment.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0) + proposer := deployment.NewTypeAndVersion(types.ProposerManyChainMultisig, deployment.Version1_0_0) + canceller := deployment.NewTypeAndVersion(types.CancellerManyChainMultisig, deployment.Version1_0_0) + bypasser := deployment.NewTypeAndVersion(types.BypasserManyChainMultisig, deployment.Version1_0_0) + + // Ensure we either have the bundle or not. + _, err := deployment.AddressesContainBundle(addresses, + map[deployment.TypeAndVersion]struct{}{ + timelock: {}, proposer: {}, canceller: {}, bypasser: {}, + }) + if err != nil { + return nil, fmt.Errorf("unable to check MCMS contracts on chain %s error: %w", chain.Name(), err) + } + for address, tvStr := range addresses { - switch tvStr.String() { - case deployment.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0).String(): + switch tvStr { + case timelock: tl, err := owner_helpers.NewRBACTimelock(common.HexToAddress(address), chain.Client) if err != nil { return nil, err } state.Timelock = tl - case deployment.NewTypeAndVersion(types.ProposerManyChainMultisig, deployment.Version1_0_0).String(): + case proposer: mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) if err != nil { return nil, err } state.ProposerMcm = mcms - case deployment.NewTypeAndVersion(types.BypasserManyChainMultisig, deployment.Version1_0_0).String(): + case bypasser: mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) if err != nil { return nil, err } state.BypasserMcm = mcms - case deployment.NewTypeAndVersion(types.CancellerManyChainMultisig, deployment.Version1_0_0).String(): + case canceller: mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) if err != nil { return nil, err @@ -97,3 +125,67 @@ func LoadMCMSWithTimelockState(chain deployment.Chain, addresses map[string]depl } return &state, nil } + +type LinkTokenState struct { + LinkToken *link_token.LinkToken +} + +func (s LinkTokenState) GenerateLinkView() (v1_0.LinkTokenView, error) { + if s.LinkToken == nil { + return v1_0.LinkTokenView{}, errors.New("link token not found") + } + return v1_0.GenerateLinkTokenView(s.LinkToken) +} + +func MaybeLoadLinkTokenState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*LinkTokenState, error) { + state := LinkTokenState{} + linkToken := deployment.NewTypeAndVersion(types.LinkToken, deployment.Version1_0_0) + // Perhaps revisit if we have a use case for multiple. + _, err := deployment.AddressesContainBundle(addresses, map[deployment.TypeAndVersion]struct{}{linkToken: {}}) + if err != nil { + return nil, fmt.Errorf("unable to check link token on chain %s error: %w", chain.Name(), err) + } + for address, tvStr := range addresses { + switch tvStr { + case linkToken: + lt, err := link_token.NewLinkToken(common.HexToAddress(address), chain.Client) + if err != nil { + return nil, err + } + state.LinkToken = lt + } + } + return &state, nil +} + +type StaticLinkTokenState struct { + StaticLinkToken *link_token_interface.LinkToken +} + +func (s StaticLinkTokenState) GenerateStaticLinkView() (v1_0.StaticLinkTokenView, error) { + if s.StaticLinkToken == nil { + return v1_0.StaticLinkTokenView{}, errors.New("static link token not found") + } + return v1_0.GenerateStaticLinkTokenView(s.StaticLinkToken) +} + +func MaybeLoadStaticLinkTokenState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*StaticLinkTokenState, error) { + state := StaticLinkTokenState{} + staticLinkToken := deployment.NewTypeAndVersion(types.StaticLinkToken, deployment.Version1_0_0) + // Perhaps revisit if we have a use case for multiple. + _, err := deployment.AddressesContainBundle(addresses, map[deployment.TypeAndVersion]struct{}{staticLinkToken: {}}) + if err != nil { + return nil, fmt.Errorf("unable to check static link token on chain %s error: %w", chain.Name(), err) + } + for address, tvStr := range addresses { + switch tvStr { + case staticLinkToken: + lt, err := link_token_interface.NewLinkToken(common.HexToAddress(address), chain.Client) + if err != nil { + return nil, err + } + state.StaticLinkToken = lt + } + } + return &state, nil +} diff --git a/deployment/common/changeset/test_helpers.go b/deployment/common/changeset/test_helpers.go index 913b4544f30..2d5295282f5 100644 --- a/deployment/common/changeset/test_helpers.go +++ b/deployment/common/changeset/test_helpers.go @@ -90,6 +90,7 @@ func ApplyChangesets(t *testing.T, e deployment.Environment, timelocksPerChain m Chains: e.Chains, NodeIDs: e.NodeIDs, Offchain: e.Offchain, + OCRSecrets: e.OCRSecrets, } } return currentEnv, nil diff --git a/deployment/common/changeset/transfer_to_mcms_with_timelock.go b/deployment/common/changeset/transfer_to_mcms_with_timelock.go new file mode 100644 index 00000000000..e48d29af92b --- /dev/null +++ b/deployment/common/changeset/transfer_to_mcms_with_timelock.go @@ -0,0 +1,144 @@ +package changeset + +import ( + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + gethtypes "github.com/ethereum/go-ethereum/core/types" + owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" +) + +type TransferToMCMSWithTimelockConfig struct { + ContractsByChain map[uint64][]common.Address + // MinDelay is for the accept ownership proposal + MinDelay time.Duration +} + +type Ownable interface { + Owner(opts *bind.CallOpts) (common.Address, error) + TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*gethtypes.Transaction, error) + AcceptOwnership(opts *bind.TransactOpts) (*gethtypes.Transaction, error) + Address() common.Address +} + +func LoadOwnableContract(addr common.Address, client bind.ContractBackend) (common.Address, Ownable, error) { + // Just using the ownership interface from here. + c, err := burn_mint_erc677.NewBurnMintERC677(addr, client) + if err != nil { + return common.Address{}, nil, fmt.Errorf("failed to create contract: %v", err) + } + owner, err := c.Owner(nil) + if err != nil { + return common.Address{}, nil, fmt.Errorf("failed to get owner of contract: %v", err) + } + return owner, c, nil +} + +func (t TransferToMCMSWithTimelockConfig) Validate(e deployment.Environment) error { + for chainSelector, contracts := range t.ContractsByChain { + for _, contract := range contracts { + // Cannot transfer an unknown address. + // Note this also assures non-zero addresses. + if exists, err := deployment.AddressBookContains(e.ExistingAddresses, chainSelector, contract.String()); err != nil || !exists { + if err != nil { + return fmt.Errorf("failed to check address book: %v", err) + } + return fmt.Errorf("contract %s not found in address book", contract) + } + owner, _, err := LoadOwnableContract(contract, e.Chains[chainSelector].Client) + if err != nil { + return fmt.Errorf("failed to load ownable: %v", err) + } + if owner != e.Chains[chainSelector].DeployerKey.From { + return fmt.Errorf("contract %s is not owned by the deployer key", contract) + } + } + // If there is no timelock and mcms proposer on the chain, the transfer will fail. + if _, err := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.RBACTimelock); err != nil { + return fmt.Errorf("timelock not present on the chain %v", err) + } + if _, err := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.ProposerManyChainMultisig); err != nil { + return fmt.Errorf("mcms proposer not present on the chain %v", err) + } + } + + return nil +} + +var _ deployment.ChangeSet[TransferToMCMSWithTimelockConfig] = TransferToMCMSWithTimelock + +// TransferToMCMSWithTimelock creates a changeset that transfers ownership of all the +// contracts in the provided configuration to the timelock on the chain and generates +// a corresponding accept ownership proposal to complete the transfer. +// It assumes that DeployMCMSWithTimelock has already been run s.t. +// the timelock and mcmses exist on the chain and that the proposed addresses to transfer ownership +// are currently owned by the deployer key. +func TransferToMCMSWithTimelock( + e deployment.Environment, + cfg TransferToMCMSWithTimelockConfig, +) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(e); err != nil { + return deployment.ChangesetOutput{}, err + } + var batches []timelock.BatchChainOperation + timelocksByChain := make(map[uint64]common.Address) + proposersByChain := make(map[uint64]*owner_helpers.ManyChainMultiSig) + for chainSelector, contracts := range cfg.ContractsByChain { + // Already validated that the timelock/proposer exists. + timelockAddr, _ := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.RBACTimelock) + proposerAddr, _ := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.ProposerManyChainMultisig) + timelocksByChain[chainSelector] = common.HexToAddress(timelockAddr) + proposer, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(proposerAddr), e.Chains[chainSelector].Client) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to create proposer mcms: %v", err) + } + proposersByChain[chainSelector] = proposer + + var ops []mcms.Operation + for _, contract := range contracts { + // Just using the ownership interface. + // Already validated is ownable. + owner, c, _ := LoadOwnableContract(contract, e.Chains[chainSelector].Client) + if owner.String() == timelockAddr { + // Already owned by timelock. + e.Logger.Infof("contract %s already owned by timelock", contract) + continue + } + tx, err := c.TransferOwnership(e.Chains[chainSelector].DeployerKey, common.HexToAddress(timelockAddr)) + _, err = deployment.ConfirmIfNoError(e.Chains[chainSelector], tx, err) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of contract %T: %v", contract, err) + } + tx, err = c.AcceptOwnership(deployment.SimTransactOpts()) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate accept ownership calldata of %s: %w", contract, err) + } + ops = append(ops, mcms.Operation{ + To: contract, + Data: tx.Data(), + Value: big.NewInt(0), + }) + } + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chainSelector), + Batch: ops, + }) + } + proposal, err := proposalutils.BuildProposalFromBatches( + timelocksByChain, proposersByChain, batches, "Transfer ownership to timelock", cfg.MinDelay) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal from batch: %w, batches: %+v", err, batches) + } + + return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{*proposal}}, nil +} diff --git a/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go b/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go new file mode 100644 index 00000000000..6cdff286707 --- /dev/null +++ b/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go @@ -0,0 +1,69 @@ +package changeset + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/stretchr/testify/require" + + "math/big" + + "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestTransferToMCMSWithTimelock(t *testing.T) { + lggr := logger.TestLogger(t) + e := memory.NewMemoryEnvironment(t, lggr, 0, memory.MemoryEnvironmentConfig{ + Chains: 1, + Nodes: 1, + }) + chain1 := e.AllChainSelectors()[0] + e, err := ApplyChangesets(t, e, nil, []ChangesetApplication{ + { + Changeset: WrapChangeSet(DeployLinkToken), + Config: []uint64{chain1}, + }, + { + Changeset: WrapChangeSet(DeployMCMSWithTimelock), + Config: map[uint64]types.MCMSWithTimelockConfig{ + chain1: { + Canceller: SingleGroupMCMS(t), + Bypasser: SingleGroupMCMS(t), + Proposer: SingleGroupMCMS(t), + TimelockExecutors: e.AllDeployerKeys(), + TimelockMinDelay: big.NewInt(0), + }, + }, + }, + }) + require.NoError(t, err) + addrs, err := e.ExistingAddresses.AddressesForChain(chain1) + require.NoError(t, err) + state, err := MaybeLoadMCMSWithTimelockState(e.Chains[chain1], addrs) + require.NoError(t, err) + link, err := MaybeLoadLinkTokenState(e.Chains[chain1], addrs) + require.NoError(t, err) + e, err = ApplyChangesets(t, e, map[uint64]*owner_helpers.RBACTimelock{ + chain1: state.Timelock, + }, []ChangesetApplication{ + { + Changeset: WrapChangeSet(TransferToMCMSWithTimelock), + Config: TransferToMCMSWithTimelockConfig{ + ContractsByChain: map[uint64][]common.Address{ + chain1: {link.LinkToken.Address()}, + }, + MinDelay: 0, + }, + }, + }) + require.NoError(t, err) + // We expect now that the link token is owned by the MCMS timelock. + link, err = MaybeLoadLinkTokenState(e.Chains[chain1], addrs) + require.NoError(t, err) + o, err := link.LinkToken.Owner(nil) + require.NoError(t, err) + require.Equal(t, state.Timelock.Address(), o) +} diff --git a/deployment/common/proposalutils/propose.go b/deployment/common/proposalutils/propose.go new file mode 100644 index 00000000000..f525c0b6643 --- /dev/null +++ b/deployment/common/proposalutils/propose.go @@ -0,0 +1,77 @@ +package proposalutils + +import ( + "fmt" + "time" + + mapset "github.com/deckarep/golang-set/v2" + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" +) + +func buildProposalMetadata( + chainSelectors []uint64, + proposerMcmsesPerChain map[uint64]*gethwrappers.ManyChainMultiSig, +) (map[mcms.ChainIdentifier]mcms.ChainMetadata, error) { + metaDataPerChain := make(map[mcms.ChainIdentifier]mcms.ChainMetadata) + for _, selector := range chainSelectors { + proposerMcms, ok := proposerMcmsesPerChain[selector] + if !ok { + return nil, fmt.Errorf("missing proposer mcm for chain %d", selector) + } + chainId := mcms.ChainIdentifier(selector) + opCount, err := proposerMcms.GetOpCount(nil) + if err != nil { + return nil, fmt.Errorf("failed to get op count for chain %d: %w", selector, err) + } + metaDataPerChain[chainId] = mcms.ChainMetadata{ + StartingOpCount: opCount.Uint64(), + MCMAddress: proposerMcms.Address(), + } + } + return metaDataPerChain, nil +} + +// BuildProposalFromBatches Given batches of operations, we build the metadata and timelock addresses of those opartions +// We then return a proposal that can be executed and signed +func BuildProposalFromBatches( + timelocksPerChain map[uint64]common.Address, + proposerMcmsesPerChain map[uint64]*gethwrappers.ManyChainMultiSig, + batches []timelock.BatchChainOperation, + description string, + minDelay time.Duration, +) (*timelock.MCMSWithTimelockProposal, error) { + if len(batches) == 0 { + return nil, fmt.Errorf("no operations in batch") + } + + chains := mapset.NewSet[uint64]() + for _, op := range batches { + chains.Add(uint64(op.ChainIdentifier)) + } + + mcmsMd, err := buildProposalMetadata(chains.ToSlice(), proposerMcmsesPerChain) + if err != nil { + return nil, err + } + + tlsPerChainId := make(map[mcms.ChainIdentifier]common.Address) + for chainId, tl := range timelocksPerChain { + tlsPerChainId[mcms.ChainIdentifier(chainId)] = tl + } + + return timelock.NewMCMSWithTimelockProposal( + "1", + 2004259681, // TODO: should be parameterized and based on current block timestamp. + []mcms.Signature{}, + false, + mcmsMd, + tlsPerChainId, + description, + batches, + timelock.Schedule, + minDelay.String(), + ) +} diff --git a/deployment/common/types/types.go b/deployment/common/types/types.go index a6504d17a94..386ef8fbb36 100644 --- a/deployment/common/types/types.go +++ b/deployment/common/types/types.go @@ -16,7 +16,16 @@ const ( CancellerManyChainMultisig deployment.ContractType = "CancellerManyChainMultiSig" ProposerManyChainMultisig deployment.ContractType = "ProposerManyChainMultiSig" RBACTimelock deployment.ContractType = "RBACTimelock" - LinkToken deployment.ContractType = "LinkToken" + // LinkToken is the burn/mint link token. It should be used everywhere for + // new deployments. Corresponds to + // https://github.com/smartcontractkit/chainlink/blob/develop/core/gethwrappers/shared/generated/link_token/link_token.go#L34 + LinkToken deployment.ContractType = "LinkToken" + // StaticLinkToken represents the (very old) non-burn/mint link token. + // It is not used in new deployments, but still exists on some chains + // and has a distinct ABI from the new LinkToken. + // Corresponds to the ABI + // https://github.com/smartcontractkit/chainlink/blob/develop/core/gethwrappers/generated/link_token_interface/link_token_interface.go#L34 + StaticLinkToken deployment.ContractType = "StaticLinkToken" ) type MCMSWithTimelockConfig struct { diff --git a/deployment/common/view/nops.go b/deployment/common/view/nops.go index b75360a287d..61e16d59145 100644 --- a/deployment/common/view/nops.go +++ b/deployment/common/view/nops.go @@ -4,13 +4,16 @@ import ( "context" "fmt" + "github.com/pkg/errors" nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink/deployment" ) type NopView struct { // NodeID is the unique identifier of the node NodeID string `json:"nodeID"` + PeerID string `json:"peerID"` IsBootstrap bool `json:"isBootstrap"` OCRKeys map[string]OCRKeyView `json:"ocrKeys"` PayeeAddress string `json:"payeeAddress"` @@ -38,7 +41,7 @@ func GenerateNopsView(nodeIds []string, oc deployment.OffchainClient) (map[strin // get node info nodeDetails, err := oc.GetNode(context.Background(), &nodev1.GetNodeRequest{Id: node.NodeID}) if err != nil { - return nv, err + return nv, errors.Wrapf(err, "failed to get node details from offchain client for node %s", node.NodeID) } if nodeDetails == nil || nodeDetails.Node == nil { return nv, fmt.Errorf("failed to get node details from offchain client for node %s", node.NodeID) @@ -49,6 +52,7 @@ func GenerateNopsView(nodeIds []string, oc deployment.OffchainClient) (map[strin } nop := NopView{ NodeID: node.NodeID, + PeerID: node.PeerID.String(), IsBootstrap: node.IsBootstrap, OCRKeys: make(map[string]OCRKeyView), PayeeAddress: node.AdminAddr, diff --git a/deployment/common/view/types/contract_state.go b/deployment/common/view/types/contract_state.go index f65c510af53..9b63d1f4db0 100644 --- a/deployment/common/view/types/contract_state.go +++ b/deployment/common/view/types/contract_state.go @@ -1,6 +1,8 @@ package types import ( + "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" ) @@ -14,11 +16,11 @@ type ContractMetaData struct { func NewContractMetaData(tv Meta, addr common.Address) (ContractMetaData, error) { tvStr, err := tv.TypeAndVersion(nil) if err != nil { - return ContractMetaData{}, err + return ContractMetaData{}, fmt.Errorf("failed to get type and version addr %s: %w", addr.String(), err) } owner, err := tv.Owner(nil) if err != nil { - return ContractMetaData{}, err + return ContractMetaData{}, fmt.Errorf("failed to get owner addr %s: %w", addr.String(), err) } return ContractMetaData{ TypeAndVersion: tvStr, diff --git a/deployment/common/view/v1_0/link_token.go b/deployment/common/view/v1_0/link_token.go new file mode 100644 index 00000000000..6dd1a00be3b --- /dev/null +++ b/deployment/common/view/v1_0/link_token.go @@ -0,0 +1,58 @@ +package v1_0 + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/deployment" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/common/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" +) + +type LinkTokenView struct { + types.ContractMetaData + Decimals uint8 `json:"decimals"` + Supply *big.Int `json:"supply"` + Minters []common.Address `json:"minters"` + Burners []common.Address `json:"burners"` +} + +func GenerateLinkTokenView(lt *link_token.LinkToken) (LinkTokenView, error) { + owner, err := lt.Owner(nil) + if err != nil { + return LinkTokenView{}, fmt.Errorf("failed to get owner %s: %w", lt.Address(), err) + } + decimals, err := lt.Decimals(nil) + if err != nil { + return LinkTokenView{}, fmt.Errorf("failed to get decimals %s: %w", lt.Address(), err) + } + totalSupply, err := lt.TotalSupply(nil) + if err != nil { + return LinkTokenView{}, fmt.Errorf("failed to get total supply %s: %w", lt.Address(), err) + } + minters, err := lt.GetMinters(nil) + if err != nil { + return LinkTokenView{}, fmt.Errorf("failed to get minters %s: %w", lt.Address(), err) + } + burners, err := lt.GetBurners(nil) + if err != nil { + return LinkTokenView{}, fmt.Errorf("failed to get burners %s: %w", lt.Address(), err) + } + return LinkTokenView{ + ContractMetaData: types.ContractMetaData{ + TypeAndVersion: deployment.TypeAndVersion{ + commontypes.LinkToken, + deployment.Version1_0_0, + }.String(), + Address: lt.Address(), + Owner: owner, + }, + Decimals: decimals, + Supply: totalSupply, + Minters: minters, + Burners: burners, + }, nil +} diff --git a/deployment/common/view/v1_0/link_token_test.go b/deployment/common/view/v1_0/link_token_test.go new file mode 100644 index 00000000000..c83c0b3e3c2 --- /dev/null +++ b/deployment/common/view/v1_0/link_token_test.go @@ -0,0 +1,53 @@ +package v1_0 + +import ( + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestLinkTokenView(t *testing.T) { + e := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + Chains: 1, + }) + chain := e.Chains[e.AllChainSelectors()[0]] + _, tx, lt, err := link_token.DeployLinkToken(chain.DeployerKey, chain.Client) + require.NoError(t, err) + _, err = chain.Confirm(tx) + require.NoError(t, err) + v, err := GenerateLinkTokenView(lt) + require.NoError(t, err) + + assert.Equal(t, v.Owner, chain.DeployerKey.From) + assert.Equal(t, v.TypeAndVersion, "LinkToken 1.0.0") + assert.Equal(t, v.Decimals, uint8(18)) + // Initially nothing minted and no minters/burners. + assert.Equal(t, v.Supply.String(), "0") + require.Len(t, v.Minters, 0) + require.Len(t, v.Burners, 0) + + // Add some minters + tx, err = lt.GrantMintAndBurnRoles(chain.DeployerKey, chain.DeployerKey.From) + require.NoError(t, err) + _, err = chain.Confirm(tx) + require.NoError(t, err) + tx, err = lt.Mint(chain.DeployerKey, chain.DeployerKey.From, big.NewInt(100)) + _, err = chain.Confirm(tx) + require.NoError(t, err) + + v, err = GenerateLinkTokenView(lt) + require.NoError(t, err) + + assert.Equal(t, v.Supply.String(), "100") + require.Len(t, v.Minters, 1) + require.Equal(t, v.Minters[0].String(), chain.DeployerKey.From.String()) + require.Len(t, v.Burners, 1) + require.Equal(t, v.Burners[0].String(), chain.DeployerKey.From.String()) +} diff --git a/deployment/common/view/v1_0/static_link_token.go b/deployment/common/view/v1_0/static_link_token.go new file mode 100644 index 00000000000..525f1a9f0c5 --- /dev/null +++ b/deployment/common/view/v1_0/static_link_token.go @@ -0,0 +1,40 @@ +package v1_0 + +import ( + "fmt" + "math/big" + + "github.com/smartcontractkit/chainlink/deployment" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/common/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" +) + +type StaticLinkTokenView struct { + types.ContractMetaData + Decimals uint8 `json:"decimals"` + Supply *big.Int `json:"supply"` +} + +func GenerateStaticLinkTokenView(lt *link_token_interface.LinkToken) (StaticLinkTokenView, error) { + decimals, err := lt.Decimals(nil) + if err != nil { + return StaticLinkTokenView{}, fmt.Errorf("failed to get decimals %s: %w", lt.Address(), err) + } + totalSupply, err := lt.TotalSupply(nil) + if err != nil { + return StaticLinkTokenView{}, fmt.Errorf("failed to get total supply %s: %w", lt.Address(), err) + } + return StaticLinkTokenView{ + ContractMetaData: types.ContractMetaData{ + TypeAndVersion: deployment.TypeAndVersion{ + commontypes.StaticLinkToken, + deployment.Version1_0_0, + }.String(), + Address: lt.Address(), + // No owner. + }, + Decimals: decimals, + Supply: totalSupply, + }, nil +} diff --git a/deployment/common/view/v1_0/static_link_token_test.go b/deployment/common/view/v1_0/static_link_token_test.go new file mode 100644 index 00000000000..517efac9438 --- /dev/null +++ b/deployment/common/view/v1_0/static_link_token_test.go @@ -0,0 +1,32 @@ +package v1_0 + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestStaticLinkTokenView(t *testing.T) { + e := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + Chains: 1, + }) + chain := e.Chains[e.AllChainSelectors()[0]] + _, tx, lt, err := link_token_interface.DeployLinkToken(chain.DeployerKey, chain.Client) + require.NoError(t, err) + _, err = chain.Confirm(tx) + require.NoError(t, err) + v, err := GenerateStaticLinkTokenView(lt) + require.NoError(t, err) + + assert.Equal(t, v.Owner, common.HexToAddress("0x0")) // Ownerless + assert.Equal(t, v.TypeAndVersion, "StaticLinkToken 1.0.0") + assert.Equal(t, v.Decimals, uint8(18)) + assert.Equal(t, v.Supply.String(), "1000000000000000000000000000") +} diff --git a/deployment/environment.go b/deployment/environment.go index c55f4d3efe6..3d120adbbf1 100644 --- a/deployment/environment.go +++ b/deployment/environment.go @@ -54,6 +54,27 @@ type Chain struct { // Note the Sign function can be abstract supporting a variety of key storage mechanisms (e.g. KMS etc). DeployerKey *bind.TransactOpts Confirm func(tx *types.Transaction) (uint64, error) + // Users are a set of keys that can be used to interact with the chain. + // These are distinct from the deployer key. + Users []*bind.TransactOpts +} + +func (c Chain) String() string { + chainInfo, err := ChainInfo(c.Selector) + if err != nil { + // we should never get here, if the selector is invalid it should not be in the environment + panic(err) + } + return fmt.Sprintf("%s (%d)", chainInfo.ChainName, chainInfo.ChainSelector) +} + +func (c Chain) Name() string { + chainInfo, err := ChainInfo(c.Selector) + if err != nil { + // we should never get here, if the selector is invalid it should not be in the environment + panic(err) + } + return chainInfo.ChainName } // Environment represents an instance of a deployed product @@ -76,6 +97,8 @@ type Environment struct { Chains map[uint64]Chain NodeIDs []string Offchain OffchainClient + GetContext func() context.Context + OCRSecrets OCRSecrets } func NewEnvironment( @@ -85,6 +108,8 @@ func NewEnvironment( chains map[uint64]Chain, nodeIDs []string, offchain OffchainClient, + ctx func() context.Context, + secrets OCRSecrets, ) *Environment { return &Environment{ Name: name, @@ -93,6 +118,8 @@ func NewEnvironment( Chains: chains, NodeIDs: nodeIDs, Offchain: offchain, + GetContext: ctx, + OCRSecrets: secrets, } } @@ -141,7 +168,7 @@ func ConfirmIfNoError(chain Chain, tx *types.Transaction, err error) (uint64, er var d rpc.DataError ok := errors.As(err, &d) if ok { - return 0, fmt.Errorf("transaction reverted: Error %s ErrorData %v", d.Error(), d.ErrorData()) + return 0, fmt.Errorf("transaction reverted on chain %s: Error %s ErrorData %v", chain.String(), d.Error(), d.ErrorData()) } return 0, err } @@ -406,6 +433,7 @@ func NodeInfo(nodeIDs []string, oc NodeChainConfigsLister) (Nodes, error) { } type CapabilityRegistryConfig struct { - EVMChainID uint64 // chain id of the chain the CR is deployed on - Contract common.Address // address of the CR contract + EVMChainID uint64 // chain id of the chain the CR is deployed on + Contract common.Address // address of the CR contract + NetworkType string // network type of the chain } diff --git a/deployment/environment/clo/don_nodeset_test.go b/deployment/environment/clo/don_nodeset_test.go index b576e95835a..fab9a81690b 100644 --- a/deployment/environment/clo/don_nodeset_test.go +++ b/deployment/environment/clo/don_nodeset_test.go @@ -61,7 +61,7 @@ func TestGenerateNopNodesData(t *testing.T) { require.NotEmpty(t, ksNops) b, err := json.MarshalIndent(ksNops, "", " ") require.NoError(t, err) - require.NoError(t, os.WriteFile("testdata/keystone_nops.json", b, 0644)) // nolint: gosec + require.NoError(t, os.WriteFile("testdata/keystone_nops.json", b, 0644)) //nolint:gosec } keystoneNops := loadTestNops(t, "testdata/keystone_nops.json") diff --git a/deployment/environment/clo/models/models_gen.go b/deployment/environment/clo/models/models_gen.go index baea1dbcbed..8d8f57c3b56 100644 --- a/deployment/environment/clo/models/models_gen.go +++ b/deployment/environment/clo/models/models_gen.go @@ -58,7 +58,7 @@ type AddAggregatorInput struct { type AddChainInput struct { NetworkID string `json:"networkID,omitempty"` Template string `json:"template,omitempty"` - // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. DisplayName *string `json:"displayName,omitempty"` } @@ -102,7 +102,7 @@ type AddLaneInput struct { ChainAid string `json:"chainAID,omitempty"` ChainBid string `json:"chainBID,omitempty"` Template string `json:"template,omitempty"` - // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. DisplayName *string `json:"displayName,omitempty"` } @@ -353,7 +353,7 @@ type CCIPChain struct { FeeTokens []string `json:"feeTokens,omitempty"` WrappedNativeToken string `json:"wrappedNativeToken,omitempty"` ArchivedAt *Time `json:"archivedAt,omitempty"` - // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. DisplayName *string `json:"displayName,omitempty"` DeployedTemplate map[string]interface{} `json:"deployedTemplate,omitempty"` Labels map[string]interface{} `json:"labels,omitempty"` @@ -1001,7 +1001,7 @@ type ImportAggregatorInput struct { type ImportChainInput struct { NetworkID string `json:"networkID,omitempty"` Template string `json:"template,omitempty"` - // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. DisplayName *string `json:"displayName,omitempty"` } @@ -1047,7 +1047,7 @@ type ImportLaneInput struct { ChainAid string `json:"chainAID,omitempty"` ChainBid string `json:"chainBID,omitempty"` Template string `json:"template,omitempty"` - // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. DisplayName *string `json:"displayName,omitempty"` } diff --git a/deployment/environment/devenv/chain.go b/deployment/environment/devenv/chain.go index cdbaf35e860..5c6c4336ed7 100644 --- a/deployment/environment/devenv/chain.go +++ b/deployment/environment/devenv/chain.go @@ -3,10 +3,12 @@ package devenv import ( "context" "fmt" + "math/big" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" chainselectors "github.com/smartcontractkit/chain-selectors" @@ -21,12 +23,68 @@ const ( // ChainConfig holds the configuration for a with a deployer key which can be used to send transactions to the chain. type ChainConfig struct { - ChainID uint64 // chain id as per EIP-155, mainly applicable for EVM chains - ChainName string // name of the chain populated from chainselector repo - ChainType string // should denote the chain family. Acceptable values are EVM, COSMOS, SOLANA, STARKNET, APTOS etc - WSRPCs []string // websocket rpcs to connect to the chain - HTTPRPCs []string // http rpcs to connect to the chain - DeployerKey *bind.TransactOpts // key to send transactions to the chain + ChainID uint64 // chain id as per EIP-155, mainly applicable for EVM chains + ChainName string // name of the chain populated from chainselector repo + ChainType string // should denote the chain family. Acceptable values are EVM, COSMOS, SOLANA, STARKNET, APTOS etc + WSRPCs []string // websocket rpcs to connect to the chain + HTTPRPCs []string // http rpcs to connect to the chain + DeployerKey *bind.TransactOpts // key to deploy and configure contracts on the chain + Users []*bind.TransactOpts // map of addresses to their transact opts to interact with the chain as users +} + +func (c *ChainConfig) SetUsers(pvtkeys []string) error { + if pvtkeys == nil { + // if no private keys are provided, set deployer key as the user + if c.DeployerKey != nil { + c.Users = []*bind.TransactOpts{c.DeployerKey} + return nil + } else { + return fmt.Errorf("no private keys provided for users, deployer key is also not set") + } + } + for _, pvtKeyStr := range pvtkeys { + pvtKey, err := crypto.HexToECDSA(pvtKeyStr) + if err != nil { + return fmt.Errorf("failed to convert private key to ECDSA: %w", err) + } + user, err := bind.NewKeyedTransactorWithChainID(pvtKey, new(big.Int).SetUint64(c.ChainID)) + if err != nil { + return fmt.Errorf("failed to create transactor: %w", err) + } + c.Users = append(c.Users, user) + } + return nil +} + +// SetDeployerKey sets the deployer key for the chain. If private key is not provided, it fetches the deployer key from KMS. +func (c *ChainConfig) SetDeployerKey(pvtKeyStr *string) error { + if pvtKeyStr != nil && *pvtKeyStr != "" { + pvtKey, err := crypto.HexToECDSA(*pvtKeyStr) + if err != nil { + return fmt.Errorf("failed to convert private key to ECDSA: %w", err) + } + deployer, err := bind.NewKeyedTransactorWithChainID(pvtKey, new(big.Int).SetUint64(c.ChainID)) + if err != nil { + return fmt.Errorf("failed to create transactor: %w", err) + } + fmt.Printf("Deployer Address: %s for chain id %d\n", deployer.From.Hex(), c.ChainID) + c.DeployerKey = deployer + return nil + } + kmsConfig, err := deployment.KMSConfigFromEnvVars() + if err != nil { + return fmt.Errorf("failed to get kms config from env vars: %w", err) + } + kmsClient, err := deployment.NewKMSClient(kmsConfig) + if err != nil { + return fmt.Errorf("failed to create KMS client: %w", err) + } + evmKMSClient := deployment.NewEVMKMSClient(kmsClient, kmsConfig.KmsDeployerKeyId) + c.DeployerKey, err = evmKMSClient.GetKMSTransactOpts(context.Background(), new(big.Int).SetUint64(c.ChainID)) + if err != nil { + return fmt.Errorf("failed to get transactor from KMS client: %w", err) + } + return nil } func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployment.Chain, error) { @@ -50,6 +108,10 @@ func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployme if ec == nil { return nil, fmt.Errorf("failed to connect to chain %s", chainCfg.ChainName) } + chainInfo, err := deployment.ChainInfo(selector) + if err != nil { + return nil, fmt.Errorf("failed to get chain info for chain %s: %w", chainCfg.ChainName, err) + } chains[selector] = deployment.Chain{ Selector: selector, Client: ec, @@ -57,28 +119,24 @@ func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployme Confirm: func(tx *types.Transaction) (uint64, error) { var blockNumber uint64 if tx == nil { - return 0, fmt.Errorf("tx was nil, nothing to confirm") + return 0, fmt.Errorf("tx was nil, nothing to confirm chain %s", chainInfo.ChainName) } ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) defer cancel() - chainId, err := ec.ChainID(ctx) - if err != nil { - return blockNumber, fmt.Errorf("failed to get chain id: %w", err) - } receipt, err := bind.WaitMined(ctx, ec, tx) if err != nil { - return blockNumber, fmt.Errorf("failed to get confirmed receipt for chain %d: %w", chainId, err) + return blockNumber, fmt.Errorf("failed to get confirmed receipt for chain %s: %w", chainInfo.ChainName, err) } if receipt == nil { - return blockNumber, fmt.Errorf("receipt was nil for tx %s", tx.Hash().Hex()) + return blockNumber, fmt.Errorf("receipt was nil for tx %s chain %s", tx.Hash().Hex(), chainInfo.ChainName) } blockNumber = receipt.BlockNumber.Uint64() if receipt.Status == 0 { errReason, err := deployment.GetErrorReasonFromTx(ec, chainCfg.DeployerKey.From, tx, receipt) if err == nil && errReason != "" { - return blockNumber, fmt.Errorf("tx %s reverted,error reason: %s", tx.Hash().Hex(), errReason) + return blockNumber, fmt.Errorf("tx %s reverted,error reason: %s chain %s", tx.Hash().Hex(), errReason, chainInfo.ChainName) } - return blockNumber, fmt.Errorf("tx %s reverted, could not decode error reason", tx.Hash().Hex()) + return blockNumber, fmt.Errorf("tx %s reverted, could not decode error reason chain %s", tx.Hash().Hex(), chainInfo.ChainName) } return blockNumber, nil }, diff --git a/deployment/environment/devenv/environment.go b/deployment/environment/devenv/environment.go index 94319d2247e..121caea43bb 100644 --- a/deployment/environment/devenv/environment.go +++ b/deployment/environment/devenv/environment.go @@ -14,18 +14,16 @@ const ( ) type EnvironmentConfig struct { - Chains []ChainConfig - HomeChainSelector uint64 - FeedChainSelector uint64 - JDConfig JDConfig + Chains []ChainConfig + JDConfig JDConfig } -func NewEnvironment(ctx context.Context, lggr logger.Logger, config EnvironmentConfig) (*deployment.Environment, *DON, error) { +func NewEnvironment(ctx func() context.Context, lggr logger.Logger, config EnvironmentConfig) (*deployment.Environment, *DON, error) { chains, err := NewChains(lggr, config.Chains) if err != nil { return nil, nil, fmt.Errorf("failed to create chains: %w", err) } - offChain, err := NewJDClient(ctx, config.JDConfig) + offChain, err := NewJDClient(ctx(), config.JDConfig) if err != nil { return nil, nil, fmt.Errorf("failed to create JD client: %w", err) } @@ -39,7 +37,7 @@ func NewEnvironment(ctx context.Context, lggr logger.Logger, config EnvironmentC } var nodeIDs []string if jd.don != nil { - err = jd.don.CreateSupportedChains(ctx, config.Chains, *jd) + err = jd.don.CreateSupportedChains(ctx(), config.Chains, *jd) if err != nil { return nil, nil, err } @@ -53,5 +51,7 @@ func NewEnvironment(ctx context.Context, lggr logger.Logger, config EnvironmentC chains, nodeIDs, offChain, + ctx, + deployment.XXXGenerateTestOCRSecrets(), ), jd.don, nil } diff --git a/deployment/environment/devenv/jd.go b/deployment/environment/devenv/jd.go index 48150340cae..818f9b09400 100644 --- a/deployment/environment/devenv/jd.go +++ b/deployment/environment/devenv/jd.go @@ -20,6 +20,7 @@ type JDConfig struct { WSRPC string Creds credentials.TransportCredentials Auth oauth2.TokenSource + GAP string NodeInfo []NodeInfo } @@ -44,14 +45,40 @@ func authTokenInterceptor(source oauth2.TokenSource) grpc.UnaryClientInterceptor } } +func gapTokenInterceptor(token string) grpc.UnaryClientInterceptor { + return func( + ctx context.Context, + method string, + req, reply any, + cc *grpc.ClientConn, + invoker grpc.UnaryInvoker, + opts ...grpc.CallOption, + ) error { + return invoker( + metadata.AppendToOutgoingContext(ctx, "x-authorization-github-jwt", "Bearer "+token), + method, req, reply, cc, opts..., + ) + } +} + func NewJDConnection(cfg JDConfig) (*grpc.ClientConn, error) { opts := []grpc.DialOption{} + interceptors := []grpc.UnaryClientInterceptor{} + if cfg.Creds != nil { opts = append(opts, grpc.WithTransportCredentials(cfg.Creds)) } if cfg.Auth != nil { - opts = append(opts, grpc.WithUnaryInterceptor(authTokenInterceptor(cfg.Auth))) + interceptors = append(interceptors, authTokenInterceptor(cfg.Auth)) } + if cfg.GAP != "" { + interceptors = append(interceptors, gapTokenInterceptor(cfg.GAP)) + } + + if len(interceptors) > 0 { + opts = append(opts, grpc.WithChainUnaryInterceptor(interceptors...)) + } + conn, err := grpc.NewClient(cfg.GRPC, opts...) if err != nil { return nil, fmt.Errorf("failed to connect Job Distributor service. Err: %w", err) diff --git a/deployment/environment/memory/chain.go b/deployment/environment/memory/chain.go index 1bb359f9c53..40a20a02416 100644 --- a/deployment/environment/memory/chain.go +++ b/deployment/environment/memory/chain.go @@ -9,17 +9,18 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient/simulated" - "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/require" chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" ) type EVMChain struct { Backend *simulated.Backend DeployerKey *bind.TransactOpts + Users []*bind.TransactOpts } func fundAddress(t *testing.T, from *bind.TransactOpts, to common.Address, amount *big.Int, backend *simulated.Backend) { @@ -42,23 +43,11 @@ func fundAddress(t *testing.T, from *bind.TransactOpts, to common.Address, amoun backend.Commit() } -func GenerateChains(t *testing.T, numChains int) map[uint64]EVMChain { +func GenerateChains(t *testing.T, numChains int, numUsers int) map[uint64]EVMChain { chains := make(map[uint64]EVMChain) for i := 0; i < numChains; i++ { chainID := chainsel.TEST_90000001.EvmChainID + uint64(i) - key, err := crypto.GenerateKey() - require.NoError(t, err) - owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - require.NoError(t, err) - // there have to be enough initial funds on each chain to allocate for all the nodes that share the given chain in the test - backend := simulated.NewBackend(types.GenesisAlloc{ - owner.From: {Balance: big.NewInt(0).Mul(big.NewInt(7000), big.NewInt(params.Ether))}}, - simulated.WithBlockGasLimit(50000000)) - backend.Commit() // ts will be now. - chains[chainID] = EVMChain{ - Backend: backend, - DeployerKey: owner, - } + chains[chainID] = evmChain(t, numUsers) } return chains } @@ -66,18 +55,34 @@ func GenerateChains(t *testing.T, numChains int) map[uint64]EVMChain { func GenerateChainsWithIds(t *testing.T, chainIDs []uint64) map[uint64]EVMChain { chains := make(map[uint64]EVMChain) for _, chainID := range chainIDs { + chains[chainID] = evmChain(t, 1) + } + return chains +} + +func evmChain(t *testing.T, numUsers int) EVMChain { + key, err := crypto.GenerateKey() + require.NoError(t, err) + owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) + require.NoError(t, err) + genesis := types.GenesisAlloc{ + owner.From: {Balance: assets.Ether(1_000_000).ToInt()}} + // create a set of user keys + var users []*bind.TransactOpts + for j := 0; j < numUsers; j++ { key, err := crypto.GenerateKey() require.NoError(t, err) - owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) + user, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) require.NoError(t, err) - backend := simulated.NewBackend(types.GenesisAlloc{ - owner.From: {Balance: big.NewInt(0).Mul(big.NewInt(700000), big.NewInt(params.Ether))}}, - simulated.WithBlockGasLimit(10000000)) - backend.Commit() // Note initializes block timestamp to now(). - chains[chainID] = EVMChain{ - Backend: backend, - DeployerKey: owner, - } + users = append(users, user) + genesis[user.From] = types.Account{Balance: assets.Ether(1_000_000).ToInt()} + } + // there have to be enough initial funds on each chain to allocate for all the nodes that share the given chain in the test + backend := simulated.NewBackend(genesis, simulated.WithBlockGasLimit(50000000)) + backend.Commit() // ts will be now. + return EVMChain{ + Backend: backend, + DeployerKey: owner, + Users: users, } - return chains } diff --git a/deployment/environment/memory/environment.go b/deployment/environment/memory/environment.go index a1478a3bf52..d6c80a92a44 100644 --- a/deployment/environment/memory/environment.go +++ b/deployment/environment/memory/environment.go @@ -3,6 +3,7 @@ package memory import ( "context" "fmt" + "strconv" "testing" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -13,6 +14,8 @@ import ( chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -23,10 +26,11 @@ const ( ) type MemoryEnvironmentConfig struct { - Chains int - Nodes int - Bootstraps int - RegistryConfig deployment.CapabilityRegistryConfig + Chains int + NumOfUsersPerChain int + Nodes int + Bootstraps int + RegistryConfig deployment.CapabilityRegistryConfig } // For placeholders like aptos @@ -43,9 +47,15 @@ func NewMemoryChain(t *testing.T, selector uint64) deployment.Chain { // Needed for environment variables on the node which point to prexisitng addresses. // i.e. CapReg. -func NewMemoryChains(t *testing.T, numChains int) map[uint64]deployment.Chain { - mchains := GenerateChains(t, numChains) - return generateMemoryChain(t, mchains) +func NewMemoryChains(t *testing.T, numChains int, numUsers int) (map[uint64]deployment.Chain, map[uint64][]*bind.TransactOpts) { + mchains := GenerateChains(t, numChains, numUsers) + users := make(map[uint64][]*bind.TransactOpts) + for id, chain := range mchains { + sel, err := chainsel.SelectorFromChainId(id) + require.NoError(t, err) + users[sel] = chain.Users + } + return generateMemoryChain(t, mchains), users } func NewMemoryChainsWithChainIDs(t *testing.T, chainIDs []uint64) map[uint64]deployment.Chain { @@ -57,34 +67,35 @@ func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]de chains := make(map[uint64]deployment.Chain) for cid, chain := range inputs { chain := chain - sel, err := chainsel.SelectorFromChainId(cid) + chainInfo, err := chainsel.GetChainDetailsByChainIDAndFamily(strconv.FormatUint(cid, 10), chainsel.FamilyEVM) require.NoError(t, err) backend := NewBackend(chain.Backend) - chains[sel] = deployment.Chain{ - Selector: sel, + chains[chainInfo.ChainSelector] = deployment.Chain{ + Selector: chainInfo.ChainSelector, Client: backend, DeployerKey: chain.DeployerKey, Confirm: func(tx *types.Transaction) (uint64, error) { if tx == nil { - return 0, fmt.Errorf("tx was nil, nothing to confirm") + return 0, fmt.Errorf("tx was nil, nothing to confirm, chain %s", chainInfo.ChainName) } for { backend.Commit() receipt, err := backend.TransactionReceipt(context.Background(), tx.Hash()) if err != nil { - t.Log("failed to get receipt", err) + t.Log("failed to get receipt", "chain", chainInfo.ChainName, err) continue } if receipt.Status == 0 { errReason, err := deployment.GetErrorReasonFromTx(chain.Backend.Client(), chain.DeployerKey.From, tx, receipt) if err == nil && errReason != "" { - return 0, fmt.Errorf("tx %s reverted,error reason: %s", tx.Hash().Hex(), errReason) + return 0, fmt.Errorf("tx %s reverted,error reason: %s chain %s", tx.Hash().Hex(), errReason, chainInfo.ChainName) } - return 0, fmt.Errorf("tx %s reverted, could not decode error reason", tx.Hash().Hex()) + return 0, fmt.Errorf("tx %s reverted, could not decode error reason chain %s", tx.Hash().Hex(), chainInfo.ChainName) } return receipt.BlockNumber.Uint64(), nil } }, + Users: chain.Users, } } return chains @@ -92,6 +103,9 @@ func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]de func NewNodes(t *testing.T, logLevel zapcore.Level, chains map[uint64]deployment.Chain, numNodes, numBootstraps int, registryConfig deployment.CapabilityRegistryConfig) map[string]Node { nodesByPeerID := make(map[string]Node) + if numNodes+numBootstraps == 0 { + return nodesByPeerID + } ports := freeport.GetN(t, numBootstraps+numNodes) // bootstrap nodes must be separate nodes from plugin nodes, // since we won't run a bootstrapper and a plugin oracle on the same @@ -110,10 +124,12 @@ func NewNodes(t *testing.T, logLevel zapcore.Level, chains map[uint64]deployment return nodesByPeerID } -func NewMemoryEnvironmentFromChainsNodes(t *testing.T, +func NewMemoryEnvironmentFromChainsNodes( + ctx func() context.Context, lggr logger.Logger, chains map[uint64]deployment.Chain, - nodes map[string]Node) deployment.Environment { + nodes map[string]Node, +) deployment.Environment { var nodeIDs []string for id := range nodes { nodeIDs = append(nodeIDs, id) @@ -125,12 +141,14 @@ func NewMemoryEnvironmentFromChainsNodes(t *testing.T, chains, nodeIDs, // Note these have the p2p_ prefix. NewMemoryJobClient(nodes), + ctx, + deployment.XXXGenerateTestOCRSecrets(), ) } // To be used by tests and any kind of deployment logic. func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Level, config MemoryEnvironmentConfig) deployment.Environment { - chains := NewMemoryChains(t, config.Chains) + chains, _ := NewMemoryChains(t, config.Chains, config.NumOfUsersPerChain) nodes := NewNodes(t, logLevel, chains, config.Nodes, config.Bootstraps, config.RegistryConfig) var nodeIDs []string for id := range nodes { @@ -143,5 +161,7 @@ func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Lev chains, nodeIDs, NewMemoryJobClient(nodes), + func() context.Context { return tests.Context(t) }, + deployment.XXXGenerateTestOCRSecrets(), ) } diff --git a/deployment/environment/memory/node_test.go b/deployment/environment/memory/node_test.go index 7cbcb66d04a..78bc2db90e5 100644 --- a/deployment/environment/memory/node_test.go +++ b/deployment/environment/memory/node_test.go @@ -8,11 +8,12 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/deployment" ) func TestNode(t *testing.T) { - chains := NewMemoryChains(t, 3) + chains, _ := NewMemoryChains(t, 3, 5) ports := freeport.GetN(t, 1) node := NewNode(t, ports[0], chains, zapcore.DebugLevel, false, deployment.CapabilityRegistryConfig{}) // We expect 3 transmitter keys diff --git a/deployment/evm_kmsclient.go b/deployment/evm_kmsclient.go index 07af77523c8..b28a3842930 100644 --- a/deployment/evm_kmsclient.go +++ b/deployment/evm_kmsclient.go @@ -8,6 +8,7 @@ import ( "encoding/hex" "fmt" "math/big" + "os" "github.com/aws/aws-sdk-go/aws/session" @@ -231,3 +232,21 @@ var awsSessionFromProfileFn = func(config KMS) *session.Session { }, })) } + +func KMSConfigFromEnvVars() (KMS, error) { + var config KMS + var exists bool + config.KmsDeployerKeyId, exists = os.LookupEnv("KMS_DEPLOYER_KEY_ID") + if !exists { + return config, fmt.Errorf("KMS_DEPLOYER_KEY_ID is required") + } + config.KmsDeployerKeyRegion, exists = os.LookupEnv("KMS_DEPLOYER_KEY_REGION") + if !exists { + return config, fmt.Errorf("KMS_DEPLOYER_KEY_REGION is required") + } + config.AwsProfileName, exists = os.LookupEnv("AWS_PROFILE") + if !exists { + return config, fmt.Errorf("AWS_PROFILE is required") + } + return config, nil +} diff --git a/deployment/go.mod b/deployment/go.mod index 96153952fe6..b9a2fdb255f 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -1,6 +1,8 @@ module github.com/smartcontractkit/chainlink/deployment -go 1.23 +go 1.23.3 + +toolchain go1.23.4 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../ @@ -21,9 +23,9 @@ require ( github.com/rs/zerolog v1.33.0 github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 - github.com/smartcontractkit/chain-selectors v1.0.31 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d + github.com/smartcontractkit/chain-selectors v1.0.34 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 @@ -108,7 +110,7 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect github.com/bytedance/sonic v1.11.6 // indirect @@ -315,7 +317,7 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a // indirect + github.com/leanovate/gopter v0.2.11 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect @@ -401,19 +403,19 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect - github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5 // indirect github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect - github.com/smartcontractkit/wsrpc v0.8.2 // indirect + github.com/smartcontractkit/wsrpc v0.8.3 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect diff --git a/deployment/go.sum b/deployment/go.sum index e63f5b1ffb7..7513309dddf 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -16,6 +16,11 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ= @@ -261,6 +266,7 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= @@ -270,10 +276,10 @@ github.com/bradleyjkemp/cupaloy/v2 v2.6.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1l github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/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= @@ -324,6 +330,7 @@ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= @@ -373,6 +380,7 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= @@ -479,7 +487,9 @@ github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -665,6 +675,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -725,6 +736,7 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -734,6 +746,10 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= @@ -757,6 +773,7 @@ github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS github.com/gophercloud/gophercloud v1.13.0 h1:8iY9d1DAbzMW6Vok1AxbbK5ZaUjzMp0tdyt4fX9IeJ0= github.com/gophercloud/gophercloud v1.13.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= @@ -1026,6 +1043,7 @@ github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -1038,8 +1056,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= -github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -1064,6 +1082,7 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 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= @@ -1179,6 +1198,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= @@ -1231,6 +1252,7 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= @@ -1251,6 +1273,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1369,37 +1392,41 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= -github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm3KUgyMDyK0v0aOtUk4= -github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= +github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc h1:2xPgOrBA7Zjjulcn31Bp6q0kOrONbEnII7iE/vSQVHk= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d h1:0tnjo1gpG16PHAouXamgDAAu6e7PWaM0Ppq6dMWnjx0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57 h1:1BMTG66HnCIz+KMBWGvyzELNM6VHGwv2WKFhN7H49Sg= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57/go.mod h1:QPiorgpbLv4+Jn4YO6xxU4ftTu4T3QN8HwX3ImP59DE= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db/go.mod h1:yjb9d4q7+m8aGbjfTbkNoNuA4PeSxcUszsSZHDrvS0E= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969 h1:M/SMFCY4URO0H1eB9r3pkRv0LS3Ofxk/GapSgGrLfFI= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969/go.mod h1:mGmRvlk54ufCufV4EBWizOGtXoXfePoFAuYEVC8EwdY= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtOAzKS4PrPIiJX65BGo1aYiYZxFVEW+jc= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 h1:lvn9Yxah+QD1/PcgijLO0dNRa28HuQWZl8Kkxh46KJc= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 h1:T0kbw07Vb6xUyA9MIJZfErMgWseWi1zf7cYvRpoq7ug= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13/go.mod h1:1CKUOzoK+Ga19WuhRH9pxZ+qUUnrlIx108VEA6qSzeQ= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= @@ -1416,10 +1443,12 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= -github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= +github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= @@ -1431,6 +1460,7 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1439,15 +1469,18 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= @@ -1584,10 +1617,13 @@ go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYr go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= @@ -1600,6 +1636,7 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/collector/pdata v1.12.0 h1:Xx5VK1p4VO0md8MWm2icwC1MnJ7f8EimKItMWw46BmA= @@ -1677,6 +1714,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -1735,6 +1773,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1743,9 +1782,12 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1785,8 +1827,11 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -1800,6 +1845,7 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= @@ -1808,6 +1854,13 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -1876,17 +1929,23 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1922,6 +1981,7 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= @@ -1937,6 +1997,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= @@ -1997,12 +2058,19 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2035,6 +2103,12 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.202.0 h1:y1iuVHMqokQbimW79ZqPZWo4CiyFu6HcCYHwSNyzlfo= google.golang.org/api v0.202.0/go.mod h1:3Jjeq7M/SFblTNCp7ES2xhq+WvGL0KeXI0joHQBfwTQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -2080,7 +2154,18 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4= google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= @@ -2102,9 +2187,14 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/stats/opentelemetry v0.0.0-20241022174616-4bb0170ac65f h1:TsfHqsKI7qhOoYugDRyFDSKAuzegDVmkSCpjUyLkb+8= @@ -2140,6 +2230,7 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= diff --git a/deployment/helpers.go b/deployment/helpers.go index e8d2d8c8d59..50f4c404b09 100644 --- a/deployment/helpers.go +++ b/deployment/helpers.go @@ -138,17 +138,18 @@ func DeployContract[C any]( ) (*ContractDeploy[C], error) { contractDeploy := deploy(chain) if contractDeploy.Err != nil { - lggr.Errorw("Failed to deploy contract", "err", contractDeploy.Err) + lggr.Errorw("Failed to deploy contract", "chain", chain.String(), "err", contractDeploy.Err) return nil, contractDeploy.Err } _, err := chain.Confirm(contractDeploy.Tx) if err != nil { - lggr.Errorw("Failed to confirm deployment", "err", err) + lggr.Errorw("Failed to confirm deployment", "chain", chain.String(), "Contract", contractDeploy.Tv.String(), "err", err) return nil, err } + lggr.Infow("Deployed contract", "Contract", contractDeploy.Tv.String(), "addr", contractDeploy.Address, "chain", chain.Selector) err = addressBook.Save(chain.Selector, contractDeploy.Address.String(), contractDeploy.Tv) if err != nil { - lggr.Errorw("Failed to save contract address", "err", err) + lggr.Errorw("Failed to save contract address", "Contract", contractDeploy.Tv.String(), "addr", contractDeploy.Address, "chain", chain.String(), "err", err) return nil, err } return &contractDeploy, nil @@ -158,9 +159,25 @@ func IsValidChainSelector(cs uint64) error { if cs == 0 { return fmt.Errorf("chain selector must be set") } - _, err := chain_selectors.ChainIdFromSelector(cs) + _, err := chain_selectors.GetSelectorFamily(cs) if err != nil { - return fmt.Errorf("invalid chain selector: %d - %w", cs, err) + return err } return nil } + +func ChainInfo(cs uint64) (chain_selectors.ChainDetails, error) { + id, err := chain_selectors.GetChainIDFromSelector(cs) + if err != nil { + return chain_selectors.ChainDetails{}, err + } + family, err := chain_selectors.GetSelectorFamily(cs) + if err != nil { + return chain_selectors.ChainDetails{}, err + } + info, err := chain_selectors.GetChainDetailsByChainIDAndFamily(id, family) + if err != nil { + return chain_selectors.ChainDetails{}, err + } + return info, nil +} diff --git a/deployment/keystone/capability_registry_deployer.go b/deployment/keystone/capability_registry_deployer.go index a4648c27905..11c85453927 100644 --- a/deployment/keystone/capability_registry_deployer.go +++ b/deployment/keystone/capability_registry_deployer.go @@ -19,8 +19,12 @@ type CapabilitiesRegistryDeployer struct { contract *capabilities_registry.CapabilitiesRegistry } -func NewCapabilitiesRegistryDeployer(lggr logger.Logger) *CapabilitiesRegistryDeployer { - return &CapabilitiesRegistryDeployer{lggr: lggr} +func NewCapabilitiesRegistryDeployer() (*CapabilitiesRegistryDeployer, error) { + lggr, err := logger.New() + if err != nil { + return nil, err + } + return &CapabilitiesRegistryDeployer{lggr: lggr}, nil } func (c *CapabilitiesRegistryDeployer) Contract() *capabilities_registry.CapabilitiesRegistry { diff --git a/deployment/keystone/changeset/accept_ownership.go b/deployment/keystone/changeset/accept_ownership.go new file mode 100644 index 00000000000..662a4c2dcfa --- /dev/null +++ b/deployment/keystone/changeset/accept_ownership.go @@ -0,0 +1,49 @@ +package changeset + +import ( + "time" + + "github.com/ethereum/go-ethereum/common" + + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/changeset" +) + +type AcceptAllOwnershipRequest struct { + ChainSelector uint64 + MinDelay time.Duration +} + +var _ deployment.ChangeSet[*AcceptAllOwnershipRequest] = AcceptAllOwnershipsProposal + +// AcceptAllOwnershipsProposal creates a MCMS proposal to call accept ownership on all the Keystone contracts in the address book. +func AcceptAllOwnershipsProposal(e deployment.Environment, req *AcceptAllOwnershipRequest) (deployment.ChangesetOutput, error) { + chainSelector := req.ChainSelector + minDelay := req.MinDelay + chain := e.Chains[chainSelector] + addrBook := e.ExistingAddresses + + r, err := kslib.GetContractSets(e.Logger, &kslib.GetContractSetsRequest{ + Chains: map[uint64]deployment.Chain{ + req.ChainSelector: chain, + }, + AddressBook: addrBook, + }) + if err != nil { + return deployment.ChangesetOutput{}, err + } + contracts := r.ContractSets[chainSelector] + + // Construct the configuration + cfg := changeset.TransferToMCMSWithTimelockConfig{ + ContractsByChain: map[uint64][]common.Address{ + chainSelector: contracts.TransferableContracts(), + }, + MinDelay: minDelay, + } + + // Create and return the changeset + return changeset.TransferToMCMSWithTimelock(e, cfg) +} diff --git a/deployment/keystone/changeset/accept_ownership_test.go b/deployment/keystone/changeset/accept_ownership_test.go new file mode 100644 index 00000000000..f205adda496 --- /dev/null +++ b/deployment/keystone/changeset/accept_ownership_test.go @@ -0,0 +1,72 @@ +package changeset_test + +import ( + "math/big" + "testing" + + owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" +) + +func TestAcceptAllOwnership(t *testing.T) { + t.Parallel() + lggr := logger.Test(t) + cfg := memory.MemoryEnvironmentConfig{ + Nodes: 1, + Chains: 2, + } + env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) + registrySel := env.AllChainSelectors()[0] + env, err := commonchangeset.ApplyChangesets(t, env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.DeployCapabilityRegistry), + Config: registrySel, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.DeployOCR3), + Config: registrySel, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.DeployForwarder), + Config: registrySel, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: map[uint64]types.MCMSWithTimelockConfig{ + registrySel: { + Canceller: commonchangeset.SingleGroupMCMS(t), + Bypasser: commonchangeset.SingleGroupMCMS(t), + Proposer: commonchangeset.SingleGroupMCMS(t), + TimelockExecutors: env.AllDeployerKeys(), + TimelockMinDelay: big.NewInt(0), + }, + }, + }, + }) + require.NoError(t, err) + addrs, err := env.ExistingAddresses.AddressesForChain(registrySel) + require.NoError(t, err) + timelock, err := commonchangeset.MaybeLoadMCMSWithTimelockState(env.Chains[registrySel], addrs) + require.NoError(t, err) + + _, err = commonchangeset.ApplyChangesets(t, env, map[uint64]*owner_helpers.RBACTimelock{ + registrySel: timelock.Timelock, + }, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.AcceptAllOwnershipsProposal), + Config: &changeset.AcceptAllOwnershipRequest{ + ChainSelector: registrySel, + MinDelay: 0, + }, + }, + }) + require.NoError(t, err) +} diff --git a/deployment/keystone/changeset/addrbook_utils.go b/deployment/keystone/changeset/addrbook_utils.go new file mode 100644 index 00000000000..4b6d6d151b1 --- /dev/null +++ b/deployment/keystone/changeset/addrbook_utils.go @@ -0,0 +1,112 @@ +package changeset + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + ccipowner "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/keystone" + capReg "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" + keystoneForwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + ocr3Capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" +) + +// contractConstructor is a function type that takes an address and a client, +// returning the contract instance and an error. +type contractConstructor[T any] func(address common.Address, client bind.ContractBackend) (*T, error) + +// getContractsFromAddrBook retrieves a list of contract instances of a specified type from the address book. +// It uses the provided constructor to initialize matching contracts for the given chain. +func getContractsFromAddrBook[T any]( + addrBook deployment.AddressBook, + chain deployment.Chain, + desiredType deployment.ContractType, + constructor contractConstructor[T], +) ([]*T, error) { + chainAddresses, err := addrBook.AddressesForChain(chain.Selector) + if err != nil { + return nil, fmt.Errorf("failed to get addresses for chain %d: %w", chain.Selector, err) + } + + var contracts []*T + for addr, typeAndVersion := range chainAddresses { + if typeAndVersion.Type == desiredType { + address := common.HexToAddress(addr) + contractInstance, err := constructor(address, chain.Client) + if err != nil { + return nil, fmt.Errorf("failed to construct %s at %s: %w", desiredType, addr, err) + } + contracts = append(contracts, contractInstance) + } + } + + if len(contracts) == 0 { + return nil, fmt.Errorf("no %s found for chain %d", desiredType, chain.Selector) + } + + return contracts, nil +} + +// capRegistriesFromAddrBook retrieves CapabilitiesRegistry contracts for the given chain. +func capRegistriesFromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ([]*capReg.CapabilitiesRegistry, error) { + return getContractsFromAddrBook[capReg.CapabilitiesRegistry]( + addrBook, + chain, + keystone.CapabilitiesRegistry, + capReg.NewCapabilitiesRegistry, + ) +} + +// ocr3FromAddrBook retrieves OCR3Capability contracts for the given chain. +func ocr3FromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ([]*ocr3Capability.OCR3Capability, error) { + return getContractsFromAddrBook[ocr3Capability.OCR3Capability]( + addrBook, + chain, + keystone.OCR3Capability, + ocr3Capability.NewOCR3Capability, + ) +} + +// forwardersFromAddrBook retrieves KeystoneForwarder contracts for the given chain. +func forwardersFromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ([]*keystoneForwarder.KeystoneForwarder, error) { + return getContractsFromAddrBook[keystoneForwarder.KeystoneForwarder]( + addrBook, + chain, + keystone.KeystoneForwarder, + keystoneForwarder.NewKeystoneForwarder, + ) +} + +// feedsConsumersFromAddrBook retrieves FeedsConsumer contracts for the given chain. +func feedsConsumersFromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ([]*feeds_consumer.KeystoneFeedsConsumer, error) { + return getContractsFromAddrBook[feeds_consumer.KeystoneFeedsConsumer]( + addrBook, + chain, + keystone.FeedConsumer, + feeds_consumer.NewKeystoneFeedsConsumer, + ) +} + +// proposersFromAddrBook retrieves ManyChainMultiSig proposer contracts for the given chain. +func proposersFromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ([]*ccipowner.ManyChainMultiSig, error) { + return getContractsFromAddrBook[ccipowner.ManyChainMultiSig]( + addrBook, + chain, + keystone.ProposerManyChainMultiSig, + ccipowner.NewManyChainMultiSig, + ) +} + +// timelocksFromAddrBook retrieves RBACTimelock contracts for the given chain. +func timelocksFromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ([]*ccipowner.RBACTimelock, error) { + return getContractsFromAddrBook[ccipowner.RBACTimelock]( + addrBook, + chain, + keystone.RBACTimelock, + ccipowner.NewRBACTimelock, + ) +} diff --git a/deployment/keystone/changeset/configure_contracts.go b/deployment/keystone/changeset/configure_contracts.go index d5bcb32243b..3a92782e12b 100644 --- a/deployment/keystone/changeset/configure_contracts.go +++ b/deployment/keystone/changeset/configure_contracts.go @@ -5,10 +5,30 @@ import ( "fmt" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) +var _ deployment.ChangeSet[InitialContractsCfg] = ConfigureInitialContractsChangeset + +type InitialContractsCfg struct { + RegistryChainSel uint64 + Dons []kslib.DonCapabilities + OCR3Config *kslib.OracleConfig +} + +func ConfigureInitialContractsChangeset(e deployment.Environment, cfg InitialContractsCfg) (deployment.ChangesetOutput, error) { + req := &kslib.ConfigureContractsRequest{ + Env: &e, + RegistryChainSel: cfg.RegistryChainSel, + Dons: cfg.Dons, + OCR3Config: cfg.OCR3Config, + } + return ConfigureInitialContracts(e.Logger, req) +} + +// Deprecated: Use ConfigureInitialContractsChangeset instead. func ConfigureInitialContracts(lggr logger.Logger, req *kslib.ConfigureContractsRequest) (deployment.ChangesetOutput, error) { if err := req.Validate(); err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to validate request: %w", err) diff --git a/deployment/keystone/changeset/deploy_consumer.go b/deployment/keystone/changeset/deploy_consumer.go new file mode 100644 index 00000000000..fc7992e2a7d --- /dev/null +++ b/deployment/keystone/changeset/deploy_consumer.go @@ -0,0 +1,31 @@ +package changeset + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink/deployment" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" +) + +type DeployFeedsConsumerRequest struct { + ChainSelector uint64 +} + +var _ deployment.ChangeSet[*DeployFeedsConsumerRequest] = DeployFeedsConsumer + +// DeployFeedsConsumer deploys the FeedsConsumer contract to the chain with the given chainSelector. +func DeployFeedsConsumer(env deployment.Environment, req *DeployFeedsConsumerRequest) (deployment.ChangesetOutput, error) { + chainSelector := req.ChainSelector + lggr := env.Logger + chain, ok := env.Chains[chainSelector] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") + } + ab := deployment.NewMemoryAddressBook() + deployResp, err := kslib.DeployFeedsConsumer(chain, ab) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy FeedsConsumer: %w", err) + } + lggr.Infof("Deployed %s chain selector %d addr %s", deployResp.Tv.String(), chain.Selector, deployResp.Address.String()) + return deployment.ChangesetOutput{AddressBook: ab}, nil +} diff --git a/deployment/keystone/changeset/deploy_consumer_test.go b/deployment/keystone/changeset/deploy_consumer_test.go new file mode 100644 index 00000000000..9a1e8f57da7 --- /dev/null +++ b/deployment/keystone/changeset/deploy_consumer_test.go @@ -0,0 +1,40 @@ +package changeset_test + +import ( + "testing" + + "go.uber.org/zap/zapcore" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" +) + +func TestDeployFeedsConsumer(t *testing.T) { + t.Parallel() + lggr := logger.Test(t) + cfg := memory.MemoryEnvironmentConfig{ + Nodes: 1, + Chains: 2, + } + env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) + + registrySel := env.AllChainSelectors()[0] + resp, err := changeset.DeployFeedsConsumer(env, &changeset.DeployFeedsConsumerRequest{ + ChainSelector: registrySel, + }) + require.NoError(t, err) + require.NotNil(t, resp) + // feeds consumer should be deployed on chain 0 + addrs, err := resp.AddressBook.AddressesForChain(registrySel) + require.NoError(t, err) + require.Len(t, addrs, 1) + + // no feeds consumer registry on chain 1 + require.NotEqual(t, registrySel, env.AllChainSelectors()[1]) + oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) + require.Len(t, oaddrs, 0) +} diff --git a/deployment/keystone/changeset/deploy_forwarder.go b/deployment/keystone/changeset/deploy_forwarder.go index 55ab0dcd86d..cf116decd54 100644 --- a/deployment/keystone/changeset/deploy_forwarder.go +++ b/deployment/keystone/changeset/deploy_forwarder.go @@ -9,24 +9,59 @@ import ( var _ deployment.ChangeSet[uint64] = DeployForwarder -func DeployForwarder(env deployment.Environment, registryChainSel uint64) (deployment.ChangesetOutput, error) { +// DeployForwarder deploys the KeystoneForwarder contract to all chains in the environment +// callers must merge the output addressbook with the existing one +// TODO: add selectors to deploy only to specific chains +func DeployForwarder(env deployment.Environment, _ uint64) (deployment.ChangesetOutput, error) { lggr := env.Logger - // expect OCR3 to be deployed & capabilities registry - regAddrs, err := env.ExistingAddresses.AddressesForChain(registryChainSel) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("no addresses found for chain %d: %w", registryChainSel, err) - } - if len(regAddrs) != 2 { - return deployment.ChangesetOutput{}, fmt.Errorf("expected 2 addresses for chain %d, got %d", registryChainSel, len(regAddrs)) - } ab := deployment.NewMemoryAddressBook() for _, chain := range env.Chains { lggr.Infow("deploying forwarder", "chainSelector", chain.Selector) - err := kslib.DeployForwarder(lggr, chain, ab) + forwarderResp, err := kslib.DeployForwarder(chain, ab) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy KeystoneForwarder to chain selector %d: %w", chain.Selector, err) } + lggr.Infof("Deployed %s chain selector %d addr %s", forwarderResp.Tv.String(), chain.Selector, forwarderResp.Address.String()) } return deployment.ChangesetOutput{AddressBook: ab}, nil } + +var _ deployment.ChangeSet[ConfigureForwardContractsRequest] = ConfigureForwardContracts + +type ConfigureForwardContractsRequest struct { + WFDonName string + // workflow don node ids in the offchain client. Used to fetch and derive the signer keys + WFNodeIDs []string + RegistryChainSel uint64 + + UseMCMS bool +} + +func (r ConfigureForwardContractsRequest) Validate() error { + if len(r.WFNodeIDs) == 0 { + return fmt.Errorf("WFNodeIDs must not be empty") + } + return nil +} + +func ConfigureForwardContracts(env deployment.Environment, req ConfigureForwardContractsRequest) (deployment.ChangesetOutput, error) { + wfDon, err := kslib.NewRegisteredDon(env, kslib.RegisteredDonConfig{ + NodeIDs: req.WFNodeIDs, + Name: req.WFDonName, + RegistryChainSel: req.RegistryChainSel, + }) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to create registered don: %w", err) + } + r, err := kslib.ConfigureForwardContracts(&env, kslib.ConfigureForwarderContractsRequest{ + Dons: []kslib.RegisteredDon{*wfDon}, + UseMCMS: req.UseMCMS, + }) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to configure forward contracts: %w", err) + } + return deployment.ChangesetOutput{ + Proposals: r.Proposals, + }, nil +} diff --git a/deployment/keystone/changeset/deploy_forwarder_test.go b/deployment/keystone/changeset/deploy_forwarder_test.go index 8d73134fc1d..32a53f1cf08 100644 --- a/deployment/keystone/changeset/deploy_forwarder_test.go +++ b/deployment/keystone/changeset/deploy_forwarder_test.go @@ -1,16 +1,18 @@ package changeset_test import ( + "fmt" "testing" "go.uber.org/zap/zapcore" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" - kslb "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" ) @@ -24,43 +26,11 @@ func TestDeployForwarder(t *testing.T) { } env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) - var ( - ocrTV = deployment.NewTypeAndVersion(kslb.OCR3Capability, deployment.Version1_0_0) - crTV = deployment.NewTypeAndVersion(kslb.CapabilitiesRegistry, deployment.Version1_0_0) - ) - registrySel := env.AllChainSelectors()[0] - t.Run("err if no capabilities registry on registry chain", func(t *testing.T) { - m := make(map[uint64]map[string]deployment.TypeAndVersion) - m[registrySel] = map[string]deployment.TypeAndVersion{ - "0x0000000000000000000000000000000000000002": ocrTV, - } - env.ExistingAddresses = deployment.NewMemoryAddressBookFromMap(m) - // capabilities registry and ocr3 must be deployed on registry chain - _, err := changeset.DeployForwarder(env, registrySel) - require.Error(t, err) - }) - - t.Run("err if no ocr3 on registry chain", func(t *testing.T) { - m := make(map[uint64]map[string]deployment.TypeAndVersion) - m[registrySel] = map[string]deployment.TypeAndVersion{ - "0x0000000000000000000000000000000000000001": crTV, - } - env.ExistingAddresses = deployment.NewMemoryAddressBookFromMap(m) - // capabilities registry and ocr3 must be deployed on registry chain - _, err := changeset.DeployForwarder(env, registrySel) - require.Error(t, err) - }) t.Run("should deploy forwarder", func(t *testing.T) { ab := deployment.NewMemoryAddressBook() - // fake capabilities registry - err := ab.Save(registrySel, "0x0000000000000000000000000000000000000001", crTV) - require.NoError(t, err) - // fake ocr3 - err = ab.Save(registrySel, "0x0000000000000000000000000000000000000002", ocrTV) - require.NoError(t, err) // deploy forwarder env.ExistingAddresses = ab resp, err := changeset.DeployForwarder(env, registrySel) @@ -78,3 +48,90 @@ func TestDeployForwarder(t *testing.T) { require.Len(t, oaddrs, 1) }) } + +func TestConfigureForwarders(t *testing.T) { + t.Parallel() + + t.Run("no mcms ", func(t *testing.T) { + for _, nChains := range []int{1, 3} { + name := fmt.Sprintf("nChains=%d", nChains) + t.Run(name, func(t *testing.T) { + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: nChains, + }) + + var wfNodes []string + for id, _ := range te.WFNodes { + wfNodes = append(wfNodes, id) + } + + cfg := changeset.ConfigureForwardContractsRequest{ + WFDonName: "test-wf-don", + WFNodeIDs: wfNodes, + RegistryChainSel: te.RegistrySelector, + } + csOut, err := changeset.ConfigureForwardContracts(te.Env, cfg) + require.NoError(t, err) + require.Nil(t, csOut.AddressBook) + require.Len(t, csOut.Proposals, 0) + // check that forwarder + // TODO set up a listener to check that the forwarder is configured + contractSet := te.ContractSets() + for selector := range te.Env.Chains { + cs, ok := contractSet[selector] + require.True(t, ok) + require.NotNil(t, cs.Forwarder) + } + }) + } + }) + + t.Run("with mcms", func(t *testing.T) { + for _, nChains := range []int{1, 3} { + name := fmt.Sprintf("nChains=%d", nChains) + t.Run(name, func(t *testing.T) { + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: nChains, + UseMCMS: true, + }) + + var wfNodes []string + for id, _ := range te.WFNodes { + wfNodes = append(wfNodes, id) + } + + cfg := changeset.ConfigureForwardContractsRequest{ + WFDonName: "test-wf-don", + WFNodeIDs: wfNodes, + RegistryChainSel: te.RegistrySelector, + UseMCMS: true, + } + csOut, err := changeset.ConfigureForwardContracts(te.Env, cfg) + require.NoError(t, err) + require.Len(t, csOut.Proposals, nChains) + require.Nil(t, csOut.AddressBook) + + timelocks := make(map[uint64]*gethwrappers.RBACTimelock) + for selector, contractSet := range te.ContractSets() { + require.NotNil(t, contractSet.Timelock) + timelocks[selector] = contractSet.Timelock + } + _, err = commonchangeset.ApplyChangesets(t, te.Env, timelocks, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.ConfigureForwardContracts), + Config: cfg, + }, + }) + require.NoError(t, err) + + }) + } + }) + +} diff --git a/deployment/keystone/changeset/deploy_ocr3.go b/deployment/keystone/changeset/deploy_ocr3.go index 6684d8e046b..0ce3d02844b 100644 --- a/deployment/keystone/changeset/deploy_ocr3.go +++ b/deployment/keystone/changeset/deploy_ocr3.go @@ -1,37 +1,77 @@ package changeset import ( + "encoding/json" "fmt" + "io" + + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) -func DeployOCR3(env deployment.Environment, config interface{}) (deployment.ChangesetOutput, error) { - registryChainSel, ok := config.(uint64) - if !ok { - return deployment.ChangesetOutput{}, deployment.ErrInvalidConfig - } +var _ deployment.ChangeSet[uint64] = DeployOCR3 + +func DeployOCR3(env deployment.Environment, registryChainSel uint64) (deployment.ChangesetOutput, error) { + lggr := env.Logger ab := deployment.NewMemoryAddressBook() // ocr3 only deployed on registry chain c, ok := env.Chains[registryChainSel] if !ok { return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") } - err := kslib.DeployOCR3(env.Logger, c, ab) + ocr3Resp, err := kslib.DeployOCR3(c, ab) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy OCR3Capability: %w", err) } + lggr.Infof("Deployed %s chain selector %d addr %s", ocr3Resp.Tv.String(), c.Selector, ocr3Resp.Address.String()) return deployment.ChangesetOutput{AddressBook: ab}, nil } -func ConfigureOCR3Contract(lggr logger.Logger, env deployment.Environment, cfg kslib.ConfigureOCR3Config) (deployment.ChangesetOutput, error) { +var _ deployment.ChangeSet[ConfigureOCR3Config] = ConfigureOCR3Contract + +type ConfigureOCR3Config struct { + ChainSel uint64 + NodeIDs []string + OCR3Config *kslib.OracleConfig + DryRun bool + WriteGeneratedConfig io.Writer // if not nil, write the generated config to this writer as JSON [OCR2OracleConfig] - _, err := kslib.ConfigureOCR3ContractFromJD(&env, cfg) + UseMCMS bool +} + +func ConfigureOCR3Contract(env deployment.Environment, cfg ConfigureOCR3Config) (deployment.ChangesetOutput, error) { + resp, err := kslib.ConfigureOCR3ContractFromJD(&env, kslib.ConfigureOCR3Config{ + ChainSel: cfg.ChainSel, + NodeIDs: cfg.NodeIDs, + OCR3Config: cfg.OCR3Config, + DryRun: cfg.DryRun, + UseMCMS: cfg.UseMCMS, + }) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to configure OCR3Capability: %w", err) } + if w := cfg.WriteGeneratedConfig; w != nil { + b, err := json.MarshalIndent(&resp.OCR2OracleConfig, "", " ") + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to marshal response output: %w", err) + } + env.Logger.Infof("Generated OCR3 config: %s", string(b)) + n, err := w.Write(b) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to write response output: %w", err) + } + if n != len(b) { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to write all bytes") + } + } // does not create any new addresses - return deployment.ChangesetOutput{}, nil + var proposals []timelock.MCMSWithTimelockProposal + if cfg.UseMCMS { + proposals = append(proposals, *resp.Proposal) + } + return deployment.ChangesetOutput{ + Proposals: proposals, + }, nil } diff --git a/deployment/keystone/changeset/deploy_ocr3_test.go b/deployment/keystone/changeset/deploy_ocr3_test.go index d3fdf118f8b..0e5fea6b7c6 100644 --- a/deployment/keystone/changeset/deploy_ocr3_test.go +++ b/deployment/keystone/changeset/deploy_ocr3_test.go @@ -1,6 +1,8 @@ package changeset_test import ( + "bytes" + "encoding/json" "testing" "go.uber.org/zap/zapcore" @@ -8,8 +10,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink-common/pkg/logger" + + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" ) @@ -37,3 +43,100 @@ func TestDeployOCR3(t *testing.T) { oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) assert.Len(t, oaddrs, 0) } + +func TestConfigureOCR3(t *testing.T) { + t.Parallel() + lggr := logger.Test(t) + + c := kslib.OracleConfig{ + MaxFaultyOracles: 1, + DeltaProgressMillis: 12345, + } + + t.Run("no mcms", func(t *testing.T) { + + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: 1, + }) + + var wfNodes []string + for id, _ := range te.WFNodes { + wfNodes = append(wfNodes, id) + } + + w := &bytes.Buffer{} + cfg := changeset.ConfigureOCR3Config{ + ChainSel: te.RegistrySelector, + NodeIDs: wfNodes, + OCR3Config: &c, + WriteGeneratedConfig: w, + UseMCMS: false, + } + + csOut, err := changeset.ConfigureOCR3Contract(te.Env, cfg) + require.NoError(t, err) + var got kslib.OCR2OracleConfig + err = json.Unmarshal(w.Bytes(), &got) + require.NoError(t, err) + assert.Len(t, got.Signers, 4) + assert.Len(t, got.Transmitters, 4) + assert.Nil(t, csOut.Proposals) + }) + + t.Run("mcms", func(t *testing.T) { + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: 1, + UseMCMS: true, + }) + + var wfNodes []string + for id, _ := range te.WFNodes { + wfNodes = append(wfNodes, id) + } + + w := &bytes.Buffer{} + cfg := changeset.ConfigureOCR3Config{ + ChainSel: te.RegistrySelector, + NodeIDs: wfNodes, + OCR3Config: &c, + WriteGeneratedConfig: w, + UseMCMS: true, + } + + csOut, err := changeset.ConfigureOCR3Contract(te.Env, cfg) + require.NoError(t, err) + var got kslib.OCR2OracleConfig + err = json.Unmarshal(w.Bytes(), &got) + require.NoError(t, err) + assert.Len(t, got.Signers, 4) + assert.Len(t, got.Transmitters, 4) + assert.NotNil(t, csOut.Proposals) + t.Logf("got: %v", csOut.Proposals[0]) + + contractSetsResp, err := kslib.GetContractSets(lggr, &kslib.GetContractSetsRequest{ + Chains: te.Env.Chains, + AddressBook: te.Env.ExistingAddresses, + }) + require.NoError(t, err) + var timelocks = map[uint64]*gethwrappers.RBACTimelock{ + te.RegistrySelector: contractSetsResp.ContractSets[te.RegistrySelector].Timelock, + } + // now apply the changeset such that the proposal is signed and execed + w2 := &bytes.Buffer{} + cfg.WriteGeneratedConfig = w2 + _, err = commonchangeset.ApplyChangesets(t, te.Env, timelocks, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.ConfigureOCR3Contract), + Config: cfg, + }, + }) + require.NoError(t, err) + }) + +} diff --git a/deployment/keystone/changeset/deploy_registry.go b/deployment/keystone/changeset/deploy_registry.go index e9b142812d7..d07e2728282 100644 --- a/deployment/keystone/changeset/deploy_registry.go +++ b/deployment/keystone/changeset/deploy_registry.go @@ -10,14 +10,17 @@ import ( var _ deployment.ChangeSet[uint64] = DeployCapabilityRegistry func DeployCapabilityRegistry(env deployment.Environment, registrySelector uint64) (deployment.ChangesetOutput, error) { + lggr := env.Logger chain, ok := env.Chains[registrySelector] if !ok { return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") } ab := deployment.NewMemoryAddressBook() - err := kslib.DeployCapabilitiesRegistry(env.Logger, chain, ab) + capabilitiesRegistryResp, err := kslib.DeployCapabilitiesRegistry(chain, ab) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) } + lggr.Infof("Deployed %s chain selector %d addr %s", capabilitiesRegistryResp.Tv.String(), chain.Selector, capabilitiesRegistryResp.Address.String()) + return deployment.ChangesetOutput{AddressBook: ab}, nil } diff --git a/deployment/keystone/changeset/helpers_test.go b/deployment/keystone/changeset/helpers_test.go new file mode 100644 index 00000000000..faf112867ce --- /dev/null +++ b/deployment/keystone/changeset/helpers_test.go @@ -0,0 +1,420 @@ +package changeset_test + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "math" + "math/big" + "sort" + "testing" + + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/deployment/keystone" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + kschangeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" +) + +func TestSetupTestEnv(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + for _, useMCMS := range []bool{true, false} { + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: 3, + UseMCMS: useMCMS, + }) + t.Run(fmt.Sprintf("set up test env using MCMS: %T", useMCMS), func(t *testing.T) { + require.NotNil(t, te.Env.ExistingAddresses) + require.Len(t, te.Env.Chains, 3) + require.NotEmpty(t, te.RegistrySelector) + require.NotNil(t, te.Env.Offchain) + r, err := te.Env.Offchain.ListNodes(ctx, &node.ListNodesRequest{}) + require.NoError(t, err) + require.Len(t, r.Nodes, 12) + }) + } +} + +type DonConfig struct { + N int +} + +func (c DonConfig) Validate() error { + if c.N < 4 { + return errors.New("N must be at least 4") + } + return nil +} + +// TODO: separate the config into different types; wf should expand to types of ocr keybundles; writer to target chains; ... +type WFDonConfig = DonConfig +type AssetDonConfig = DonConfig +type WriterDonConfig = DonConfig + +type TestConfig struct { + WFDonConfig + AssetDonConfig + WriterDonConfig + NumChains int + + UseMCMS bool +} + +func (c TestConfig) Validate() error { + if err := c.WFDonConfig.Validate(); err != nil { + return err + } + if err := c.AssetDonConfig.Validate(); err != nil { + return err + } + if err := c.WriterDonConfig.Validate(); err != nil { + return err + } + if c.NumChains < 1 { + return errors.New("NumChains must be at least 1") + } + return nil +} + +type TestEnv struct { + t *testing.T + Env deployment.Environment + RegistrySelector uint64 + + WFNodes map[string]memory.Node + CWNodes map[string]memory.Node + AssetNodes map[string]memory.Node +} + +func (te TestEnv) ContractSets() map[uint64]kslib.ContractSet { + r, err := kslib.GetContractSets(te.Env.Logger, &kslib.GetContractSetsRequest{ + Chains: te.Env.Chains, + AddressBook: te.Env.ExistingAddresses, + }) + require.NoError(te.t, err) + return r.ContractSets +} + +// SetupTestEnv sets up a keystone test environment with the given configuration +func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { + require.NoError(t, c.Validate()) + lggr := logger.Test(t) + ctx := tests.Context(t) + chains, _ := memory.NewMemoryChains(t, c.NumChains, 1) + registryChainSel := registryChain(t, chains) + // note that all the nodes require TOML configuration of the cap registry address + // and writers need forwarder address as TOML config + // we choose to use changesets to deploy the initial contracts because that's how it's done in the real world + // this requires a initial environment to house the address book + e := deployment.Environment{ + Logger: lggr, + Chains: chains, + ExistingAddresses: deployment.NewMemoryAddressBook(), + } + e, err := commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(kschangeset.DeployCapabilityRegistry), + Config: registryChainSel, + }, + { + Changeset: commonchangeset.WrapChangeSet(kschangeset.DeployOCR3), + Config: registryChainSel, + }, + { + Changeset: commonchangeset.WrapChangeSet(kschangeset.DeployForwarder), + Config: registryChainSel, + }, + }) + require.NoError(t, err) + require.NotNil(t, e) + require.Len(t, e.Chains, c.NumChains) + validateInitialChainState(t, e, registryChainSel) + // now that we have the initial contracts deployed, we can configure the nodes with the addresses + // TODO: configure the nodes with the correct override functions + crConfig := deployment.CapabilityRegistryConfig{ + EVMChainID: registryChainSel, + Contract: [20]byte{}, + } + + wfChains := map[uint64]deployment.Chain{} + wfChains[registryChainSel] = chains[registryChainSel] + wfNodes := memory.NewNodes(t, zapcore.InfoLevel, wfChains, c.WFDonConfig.N, 0, crConfig) + require.Len(t, wfNodes, c.WFDonConfig.N) + + writerChains := map[uint64]deployment.Chain{} + maps.Copy(writerChains, chains) + cwNodes := memory.NewNodes(t, zapcore.InfoLevel, writerChains, c.WriterDonConfig.N, 0, crConfig) + require.Len(t, cwNodes, c.WriterDonConfig.N) + + assetChains := map[uint64]deployment.Chain{} + assetChains[registryChainSel] = chains[registryChainSel] + assetNodes := memory.NewNodes(t, zapcore.InfoLevel, assetChains, c.AssetDonConfig.N, 0, crConfig) + require.Len(t, assetNodes, c.AssetDonConfig.N) + + // TODO: partition nodes into multiple nops + + wfDon := keystone.DonCapabilities{ + Name: keystone.WFDonName, + Nops: []keystone.NOP{ + { + Name: "nop 1", + Nodes: maps.Keys(wfNodes), + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.OCR3Cap}, + } + cwDon := keystone.DonCapabilities{ + Name: keystone.TargetDonName, + Nops: []keystone.NOP{ + { + Name: "nop 2", + Nodes: maps.Keys(cwNodes), + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.WriteChainCap}, + } + assetDon := keystone.DonCapabilities{ + Name: keystone.StreamDonName, + Nops: []keystone.NOP{ + { + Name: "nop 3", + Nodes: maps.Keys(assetNodes), + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.StreamTriggerCap}, + } + + allChains := make(map[uint64]deployment.Chain) + maps.Copy(allChains, chains) + + allNodes := make(map[string]memory.Node) + maps.Copy(allNodes, wfNodes) + maps.Copy(allNodes, cwNodes) + maps.Copy(allNodes, assetNodes) + env := memory.NewMemoryEnvironmentFromChainsNodes(func() context.Context { return ctx }, lggr, allChains, allNodes) + // set the env addresses to the deployed addresses that were created prior to configuring the nodes + err = env.ExistingAddresses.Merge(e.ExistingAddresses) + require.NoError(t, err) + + var ocr3Config = keystone.OracleConfig{ + MaxFaultyOracles: len(wfNodes) / 3, + } + var allDons = []keystone.DonCapabilities{wfDon, cwDon, assetDon} + + _, err = kschangeset.ConfigureInitialContractsChangeset(env, kschangeset.InitialContractsCfg{ + RegistryChainSel: registryChainSel, + Dons: allDons, + OCR3Config: &ocr3Config, + }) + require.NoError(t, err) + // TODO: KS-rm_deploy_opt + //require.Nil(t, csOut.AddressBook, "no new addresses should be created in configure initial contracts") + //require.NoError(t, env.ExistingAddresses.Merge(csOut.AddressBook)) + + req := &keystone.GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: env.ExistingAddresses, + } + + contractSetsResp, err := keystone.GetContractSets(lggr, req) + require.NoError(t, err) + require.Len(t, contractSetsResp.ContractSets, len(env.Chains)) + // check the registry + gotRegistry := contractSetsResp.ContractSets[registryChainSel].CapabilitiesRegistry + require.NotNil(t, gotRegistry) + // validate the registry + // check the nodes + gotNodes, err := gotRegistry.GetNodes(nil) + require.NoError(t, err) + require.Len(t, gotNodes, len(allNodes)) + validateNodes(t, gotRegistry, wfNodes, expectedHashedCapabilities(t, gotRegistry, wfDon)) + validateNodes(t, gotRegistry, cwNodes, expectedHashedCapabilities(t, gotRegistry, cwDon)) + validateNodes(t, gotRegistry, assetNodes, expectedHashedCapabilities(t, gotRegistry, assetDon)) + + // check the dons + validateDon(t, gotRegistry, wfNodes, wfDon) + validateDon(t, gotRegistry, cwNodes, cwDon) + validateDon(t, gotRegistry, assetNodes, assetDon) + + if c.UseMCMS { + // TODO: mcms on all the chains, currently only on the registry chain. need to fix this for forwarders + // deploy, configure and xfer ownership of MCMS + timelockCfgs := make(map[uint64]commontypes.MCMSWithTimelockConfig) + for sel := range env.Chains { + t.Logf("Enabling MCMS on chain %d", sel) + timelockCfgs[sel] = commontypes.MCMSWithTimelockConfig{ + Canceller: commonchangeset.SingleGroupMCMS(t), + Bypasser: commonchangeset.SingleGroupMCMS(t), + Proposer: commonchangeset.SingleGroupMCMS(t), + TimelockExecutors: env.AllDeployerKeys(), + TimelockMinDelay: big.NewInt(0), + } + } + env, err = commonchangeset.ApplyChangesets(t, env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: timelockCfgs, + }, + }) + require.NoError(t, err) + // extract the MCMS address + r, err := kslib.GetContractSets(lggr, &kslib.GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: env.ExistingAddresses, + }) + require.NoError(t, err) + for sel := range env.Chains { + mcms := r.ContractSets[sel].MCMSWithTimelockState + require.NotNil(t, mcms, "MCMS not found on chain %d", sel) + require.NoError(t, mcms.Validate()) + + // transfer ownership of all contracts to the MCMS + env, err = commonchangeset.ApplyChangesets(t, env, map[uint64]*gethwrappers.RBACTimelock{sel: mcms.Timelock}, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(kschangeset.AcceptAllOwnershipsProposal), + Config: &kschangeset.AcceptAllOwnershipRequest{ + ChainSelector: sel, + MinDelay: 0, + }, + }, + }) + require.NoError(t, err) + } + } + return TestEnv{ + t: t, + Env: env, + RegistrySelector: registryChainSel, + WFNodes: wfNodes, + CWNodes: cwNodes, + AssetNodes: assetNodes, + } +} + +func registryChain(t *testing.T, chains map[uint64]deployment.Chain) uint64 { + var registryChainSel uint64 = math.MaxUint64 + for sel := range chains { + if sel < registryChainSel { + registryChainSel = sel + } + } + return registryChainSel +} + +// validateInitialChainState checks that the initial chain state +// has the expected contracts deployed +func validateInitialChainState(t *testing.T, env deployment.Environment, registryChainSel uint64) { + ad := env.ExistingAddresses + // all contracts on registry chain + registryChainAddrs, err := ad.AddressesForChain(registryChainSel) + require.NoError(t, err) + require.Len(t, registryChainAddrs, 3) // registry, ocr3, forwarder + // only forwarder on non-home chain + for sel := range env.Chains { + chainAddrs, err := ad.AddressesForChain(sel) + require.NoError(t, err) + if sel != registryChainSel { + require.Len(t, chainAddrs, 1) + } else { + require.Len(t, chainAddrs, 3) + } + containsForwarder := false + for _, tv := range chainAddrs { + if tv.Type == keystone.KeystoneForwarder { + containsForwarder = true + break + } + } + require.True(t, containsForwarder, "no forwarder found in %v on chain %d for target don", chainAddrs, sel) + } +} + +// validateNodes checks that the nodes exist and have the expected capabilities +func validateNodes(t *testing.T, gotRegistry *kcr.CapabilitiesRegistry, nodes map[string]memory.Node, expectedHashedCaps [][32]byte) { + gotNodes, err := gotRegistry.GetNodesByP2PIds(nil, p2pIDs(t, maps.Keys(nodes))) + require.NoError(t, err) + require.Len(t, gotNodes, len(nodes)) + for _, n := range gotNodes { + require.Equal(t, expectedHashedCaps, n.HashedCapabilityIds) + } +} + +// validateDon checks that the don exists and has the expected capabilities +func validateDon(t *testing.T, gotRegistry *kcr.CapabilitiesRegistry, nodes map[string]memory.Node, don kslib.DonCapabilities) { + gotDons, err := gotRegistry.GetDONs(nil) + require.NoError(t, err) + wantP2PID := sortedHash(p2pIDs(t, maps.Keys(nodes))) + found := false + for _, have := range gotDons { + gotP2PID := sortedHash(have.NodeP2PIds) + if gotP2PID == wantP2PID { + found = true + gotCapIDs := capIDs(t, have.CapabilityConfigurations) + require.Equal(t, expectedHashedCapabilities(t, gotRegistry, don), gotCapIDs) + break + } + } + require.True(t, found, "don not found in registry") +} + +func capIDs(t *testing.T, cfgs []kcr.CapabilitiesRegistryCapabilityConfiguration) [][32]byte { + var out [][32]byte + for _, cfg := range cfgs { + out = append(out, cfg.CapabilityId) + } + return out +} + +func ptr[T any](t T) *T { + return &t +} + +func p2pIDs(t *testing.T, vals []string) [][32]byte { + var out [][32]byte + for _, v := range vals { + id, err := p2pkey.MakePeerID(v) + require.NoError(t, err) + out = append(out, id) + } + return out +} + +func expectedHashedCapabilities(t *testing.T, registry *kcr.CapabilitiesRegistry, don kslib.DonCapabilities) [][32]byte { + out := make([][32]byte, len(don.Capabilities)) + var err error + for i, cap := range don.Capabilities { + out[i], err = registry.GetHashedCapabilityId(nil, cap.LabelledName, cap.Version) + require.NoError(t, err) + } + return out +} + +func sortedHash(p2pids [][32]byte) string { + sha256Hash := sha256.New() + sort.Slice(p2pids, func(i, j int) bool { + return bytes.Compare(p2pids[i][:], p2pids[j][:]) < 0 + }) + for _, id := range p2pids { + sha256Hash.Write(id[:]) + } + return hex.EncodeToString(sha256Hash.Sum(nil)) +} diff --git a/deployment/keystone/changeset/internal/test/utils.go b/deployment/keystone/changeset/internal/test/utils.go index cea20fd327d..6fe4a8f4a2e 100644 --- a/deployment/keystone/changeset/internal/test/utils.go +++ b/deployment/keystone/changeset/internal/test/utils.go @@ -13,11 +13,12 @@ import ( capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/memory" kslib "github.com/smartcontractkit/chainlink/deployment/keystone" - internal "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" @@ -43,7 +44,7 @@ type SetupTestRegistryResponse struct { func SetupTestRegistry(t *testing.T, lggr logger.Logger, req *SetupTestRegistryRequest) *SetupTestRegistryResponse { chain := testChain(t) // deploy the registry - registry := deployCapReg(t, lggr, chain) + registry := deployCapReg(t, chain) // convert req to nodeoperators nops := make([]kcr.CapabilitiesRegistryNodeOperator, 0) for nop := range req.NopToNodes { @@ -101,18 +102,33 @@ func SetupTestRegistry(t *testing.T, lggr logger.Logger, req *SetupTestRegistryR } } -func deployCapReg(t *testing.T, lggr logger.Logger, chain deployment.Chain) *kcr.CapabilitiesRegistry { - capabilitiesRegistryDeployer := kslib.NewCapabilitiesRegistryDeployer(lggr) - _, err := capabilitiesRegistryDeployer.Deploy(kslib.DeployRequest{Chain: chain}) +func deployCapReg(t *testing.T, chain deployment.Chain) *kcr.CapabilitiesRegistry { + capabilitiesRegistryDeployer, err := kslib.NewCapabilitiesRegistryDeployer() + require.NoError(t, err) + _, err = capabilitiesRegistryDeployer.Deploy(kslib.DeployRequest{Chain: chain}) require.NoError(t, err) return capabilitiesRegistryDeployer.Contract() } func addNops(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *kcr.CapabilitiesRegistry, nops []kcr.CapabilitiesRegistryNodeOperator) *kslib.RegisterNOPSResponse { + env := &deployment.Environment{ + Logger: lggr, + Chains: map[uint64]deployment.Chain{ + chain.Selector: chain, + }, + ExistingAddresses: deployment.NewMemoryAddressBookFromMap(map[uint64]map[string]deployment.TypeAndVersion{ + chain.Selector: { + registry.Address().String(): deployment.TypeAndVersion{ + Type: kslib.CapabilitiesRegistry, + Version: deployment.Version1_0_0, + }, + }, + }), + } resp, err := kslib.RegisterNOPS(context.TODO(), lggr, kslib.RegisterNOPSRequest{ - Chain: chain, - Registry: registry, - Nops: nops, + Env: env, + RegistryChainSelector: chain.Selector, + Nops: nops, }) require.NoError(t, err) return resp @@ -142,7 +158,6 @@ func addDons(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry cc.Config = defaultCapConfig(t, ccfg.Capability) } var exists bool - //var cc kcr.CapabilitiesRegistryCapabilityConfiguration{} cc.CapabilityId, exists = capCache.Get(ccfg.Capability) require.True(t, exists, "capability not found in cache %v", ccfg.Capability) capConfigs = append(capConfigs, cc) @@ -240,7 +255,7 @@ func (cc *CapabilityCache) AddCapabilities(lggr logger.Logger, chain deployment. } func testChain(t *testing.T) deployment.Chain { - chains := memory.NewMemoryChains(t, 1) + chains, _ := memory.NewMemoryChains(t, 1, 5) var chain deployment.Chain for _, c := range chains { chain = c diff --git a/deployment/keystone/changeset/internal/update_nodes_test.go b/deployment/keystone/changeset/internal/update_nodes_test.go index 395f1060465..b167f210811 100644 --- a/deployment/keystone/changeset/internal/update_nodes_test.go +++ b/deployment/keystone/changeset/internal/update_nodes_test.go @@ -14,9 +14,10 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" kslib "github.com/smartcontractkit/chainlink/deployment/keystone" - internal "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -679,7 +680,7 @@ func testPeerID(t *testing.T, s string) p2pkey.PeerID { } func testChain(t *testing.T) deployment.Chain { - chains := memory.NewMemoryChains(t, 1) + chains, _ := memory.NewMemoryChains(t, 1, 5) var chain deployment.Chain for _, c := range chains { chain = c diff --git a/deployment/keystone/consumer_deployer.go b/deployment/keystone/consumer_deployer.go new file mode 100644 index 00000000000..12d148144b5 --- /dev/null +++ b/deployment/keystone/consumer_deployer.go @@ -0,0 +1,55 @@ +package keystone + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" +) + +type KeystoneFeedsConsumerDeployer struct { + lggr logger.Logger + contract *feeds_consumer.KeystoneFeedsConsumer +} + +func NewKeystoneFeedsConsumerDeployer() (*KeystoneFeedsConsumerDeployer, error) { + lggr, err := logger.New() + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerDeployer{lggr: lggr}, nil +} + +func (c *KeystoneFeedsConsumerDeployer) deploy(req DeployRequest) (*DeployResponse, error) { + est, err := estimateDeploymentGas(req.Chain.Client, feeds_consumer.KeystoneFeedsConsumerABI) + if err != nil { + return nil, fmt.Errorf("failed to estimate gas: %w", err) + } + c.lggr.Debugf("Feeds Consumer estimated gas: %d", est) + + consumerAddr, tx, consumer, err := feeds_consumer.DeployKeystoneFeedsConsumer( + req.Chain.DeployerKey, + req.Chain.Client) + if err != nil { + return nil, fmt.Errorf("failed to deploy feeds consumer: %w", err) + } + + _, err = req.Chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm and save feeds consumer: %w", err) + } + + tv := deployment.TypeAndVersion{ + Type: FeedConsumer, + } + + resp := &DeployResponse{ + Address: consumerAddr, + Tx: tx.Hash(), + Tv: tv, + } + c.contract = consumer + return resp, nil +} diff --git a/deployment/keystone/contract_set.go b/deployment/keystone/contract_set.go index ccd89f6905f..ee503a54b4d 100644 --- a/deployment/keystone/contract_set.go +++ b/deployment/keystone/contract_set.go @@ -3,8 +3,6 @@ package keystone import ( "fmt" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" ) @@ -18,7 +16,7 @@ type deployContractSetResponse struct { deployment.AddressBook } -func deployContractsToChain(lggr logger.Logger, req deployContractsRequest) (*deployContractSetResponse, error) { +func deployContractsToChain(req deployContractsRequest) (*deployContractSetResponse, error) { if req.ad == nil { req.ad = deployment.NewMemoryAddressBook() } @@ -29,16 +27,16 @@ func deployContractsToChain(lggr logger.Logger, req deployContractsRequest) (*de // cap reg and ocr3 only deployed on registry chain if req.isRegistryChain { - err := DeployCapabilitiesRegistry(lggr, req.chain, resp.AddressBook) + _, err := DeployCapabilitiesRegistry(req.chain, resp.AddressBook) if err != nil { return nil, fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) } - err = DeployOCR3(lggr, req.chain, resp.AddressBook) + _, err = DeployOCR3(req.chain, resp.AddressBook) if err != nil { return nil, fmt.Errorf("failed to deploy OCR3Capability: %w", err) } } - err := DeployForwarder(lggr, req.chain, resp.AddressBook) + _, err := DeployForwarder(req.chain, resp.AddressBook) if err != nil { return nil, fmt.Errorf("failed to deploy KeystoneForwarder: %w", err) } @@ -47,48 +45,71 @@ func deployContractsToChain(lggr logger.Logger, req deployContractsRequest) (*de // DeployCapabilitiesRegistry deploys the CapabilitiesRegistry contract to the chain // and saves the address in the address book. This mutates the address book. -func DeployCapabilitiesRegistry(lggr logger.Logger, chain deployment.Chain, ab deployment.AddressBook) error { - capabilitiesRegistryDeployer := CapabilitiesRegistryDeployer{lggr: lggr} +func DeployCapabilitiesRegistry(chain deployment.Chain, ab deployment.AddressBook) (*DeployResponse, error) { + capabilitiesRegistryDeployer, err := NewCapabilitiesRegistryDeployer() capabilitiesRegistryResp, err := capabilitiesRegistryDeployer.Deploy(DeployRequest{Chain: chain}) if err != nil { - return fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) + return nil, fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) } err = ab.Save(chain.Selector, capabilitiesRegistryResp.Address.String(), capabilitiesRegistryResp.Tv) if err != nil { - return fmt.Errorf("failed to save CapabilitiesRegistry: %w", err) + return nil, fmt.Errorf("failed to save CapabilitiesRegistry: %w", err) } - lggr.Infof("Deployed %s chain selector %d addr %s", capabilitiesRegistryResp.Tv.String(), chain.Selector, capabilitiesRegistryResp.Address.String()) - return nil + return capabilitiesRegistryResp, nil } // DeployOCR3 deploys the OCR3Capability contract to the chain // and saves the address in the address book. This mutates the address book. -func DeployOCR3(lggr logger.Logger, chain deployment.Chain, ab deployment.AddressBook) error { - ocr3Deployer := OCR3Deployer{lggr: lggr} +func DeployOCR3(chain deployment.Chain, ab deployment.AddressBook) (*DeployResponse, error) { + ocr3Deployer, err := NewOCR3Deployer() + if err != nil { + return nil, fmt.Errorf("failed to create OCR3Deployer: %w", err) + } ocr3Resp, err := ocr3Deployer.deploy(DeployRequest{Chain: chain}) if err != nil { - return fmt.Errorf("failed to deploy OCR3Capability: %w", err) + return nil, fmt.Errorf("failed to deploy OCR3Capability: %w", err) } err = ab.Save(chain.Selector, ocr3Resp.Address.String(), ocr3Resp.Tv) if err != nil { - return fmt.Errorf("failed to save OCR3Capability: %w", err) + return nil, fmt.Errorf("failed to save OCR3Capability: %w", err) } - lggr.Infof("Deployed %s chain selector %d addr %s", ocr3Resp.Tv.String(), chain.Selector, ocr3Resp.Address.String()) - return nil + + return ocr3Resp, nil } // DeployForwarder deploys the KeystoneForwarder contract to the chain // and saves the address in the address book. This mutates the address book. -func DeployForwarder(lggr logger.Logger, chain deployment.Chain, ab deployment.AddressBook) error { - forwarderDeployer := KeystoneForwarderDeployer{lggr: lggr} +func DeployForwarder(chain deployment.Chain, ab deployment.AddressBook) (*DeployResponse, error) { + forwarderDeployer, err := NewKeystoneForwarderDeployer() + if err != nil { + return nil, fmt.Errorf("failed to create KeystoneForwarderDeployer: %w", err) + } forwarderResp, err := forwarderDeployer.deploy(DeployRequest{Chain: chain}) if err != nil { - return fmt.Errorf("failed to deploy KeystoneForwarder: %w", err) + return nil, fmt.Errorf("failed to deploy KeystoneForwarder: %w", err) } err = ab.Save(chain.Selector, forwarderResp.Address.String(), forwarderResp.Tv) if err != nil { - return fmt.Errorf("failed to save KeystoneForwarder: %w", err) + return nil, fmt.Errorf("failed to save KeystoneForwarder: %w", err) + } + return forwarderResp, nil +} + +// DeployFeedsConsumer deploys the KeystoneFeedsConsumer contract to the chain +// and saves the address in the address book. This mutates the address book. +func DeployFeedsConsumer(chain deployment.Chain, ab deployment.AddressBook) (*DeployResponse, error) { + consumerDeploy, err := NewKeystoneFeedsConsumerDeployer() + if err != nil { + return nil, err + } + consumerResp, err := consumerDeploy.deploy(DeployRequest{Chain: chain}) + if err != nil { + return nil, fmt.Errorf("failed to deploy FeedsConsumer: %w", err) + } + err = ab.Save(chain.Selector, consumerResp.Address.String(), consumerResp.Tv) + if err != nil { + + return nil, fmt.Errorf("failed to save FeedsConsumer: %w", err) } - lggr.Infof("Deployed %s chain selector %d addr %s", forwarderResp.Tv.String(), chain.Selector, forwarderResp.Address.String()) - return nil + return consumerResp, nil } diff --git a/deployment/keystone/deploy.go b/deployment/keystone/deploy.go index 874b98600ae..9bd291e9c1e 100644 --- a/deployment/keystone/deploy.go +++ b/deployment/keystone/deploy.go @@ -7,16 +7,23 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" "sort" "strconv" "strings" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" "golang.org/x/exp/maps" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/durationpb" @@ -25,6 +32,7 @@ import ( capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" kf "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" @@ -36,9 +44,10 @@ type ConfigureContractsRequest struct { RegistryChainSel uint64 Env *deployment.Environment - Dons []DonCapabilities // externally sourced based on the environment - OCR3Config *OracleConfigWithSecrets // TODO: probably should be a map of don to config; but currently we only have one wf don therefore one config + Dons []DonCapabilities // externally sourced based on the environment + OCR3Config *OracleConfig // TODO: probably should be a map of don to config; but currently we only have one wf don therefore one config + // TODO rm this option; unused DoContractDeploy bool // if false, the contracts are assumed to be deployed and the address book is used } @@ -73,21 +82,7 @@ func ConfigureContracts(ctx context.Context, lggr logger.Logger, req ConfigureCo return nil, fmt.Errorf("invalid request: %w", err) } - addrBook := req.Env.ExistingAddresses - if req.DoContractDeploy { - contractDeployCS, err := DeployContracts(lggr, req.Env, req.RegistryChainSel) - if err != nil { - return nil, fmt.Errorf("failed to deploy contracts: %w", err) - } - addrBook = contractDeployCS.AddressBook - } else { - lggr.Debug("skipping contract deployment") - } - if addrBook == nil { - return nil, errors.New("address book is nil") - } - - cfgRegistryResp, err := ConfigureRegistry(ctx, lggr, req, addrBook) + cfgRegistryResp, err := ConfigureRegistry(ctx, lggr, req, req.Env.ExistingAddresses) if err != nil { return nil, fmt.Errorf("failed to configure registry: %w", err) } @@ -102,31 +97,33 @@ func ConfigureContracts(ctx context.Context, lggr logger.Logger, req ConfigureCo if err != nil { return nil, fmt.Errorf("failed to assimilate registry to Dons: %w", err) } - err = ConfigureForwardContracts(req.Env, dons, addrBook) + // ignore response because we are not using mcms here and therefore no proposals are returned + _, err = ConfigureForwardContracts(req.Env, ConfigureForwarderContractsRequest{ + Dons: dons, + }) if err != nil { return nil, fmt.Errorf("failed to configure forwarder contracts: %w", err) } - err = ConfigureOCR3Contract(req.Env, req.RegistryChainSel, dons, addrBook, req.OCR3Config) + err = ConfigureOCR3Contract(req.Env, req.RegistryChainSel, dons, req.OCR3Config) if err != nil { return nil, fmt.Errorf("failed to configure OCR3 contract: %w", err) } return &ConfigureContractsResponse{ - Changeset: &deployment.ChangesetOutput{ - AddressBook: addrBook, - }, - DonInfos: cfgRegistryResp.DonInfos, + Changeset: &deployment.ChangesetOutput{}, // no new addresses, proposals etc + DonInfos: cfgRegistryResp.DonInfos, }, nil } // DeployContracts deploys the all the keystone contracts on all chains and returns the address book in the changeset -func DeployContracts(lggr logger.Logger, e *deployment.Environment, chainSel uint64) (*deployment.ChangesetOutput, error) { +func DeployContracts(e *deployment.Environment, chainSel uint64) (*deployment.ChangesetOutput, error) { + lggr := e.Logger adbook := deployment.NewMemoryAddressBook() // deploy contracts on all chains and track the registry and ocr3 contracts for _, chain := range e.Chains { lggr.Infow("deploying contracts", "chain", chain.Selector) - deployResp, err := deployContractsToChain(lggr, deployContractsRequest{ + deployResp, err := deployContractsToChain(deployContractsRequest{ chain: chain, isRegistryChain: chain.Selector == chainSel, }, @@ -147,6 +144,7 @@ func DeployContracts(lggr logger.Logger, e *deployment.Environment, chainSel uin // DonInfo is DonCapabilities, but expanded to contain node information type DonInfo struct { Name string + F uint8 Nodes []deployment.Node Capabilities []kcr.CapabilitiesRegistryCapability // every capability is hosted on each node } @@ -164,6 +162,7 @@ func DonInfos(dons []DonCapabilities, jd deployment.OffchainClient) ([]DonInfo, } donInfos = append(donInfos, DonInfo{ Name: don.Name, + F: don.F, Nodes: nodes, Capabilities: don.Capabilities, }) @@ -171,38 +170,41 @@ func DonInfos(dons []DonCapabilities, jd deployment.OffchainClient) ([]DonInfo, return donInfos, nil } -// ConfigureRegistry configures the registry contract with the given DONS and their capabilities -// the address book is required to contain the addresses of the deployed registry contract -func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureContractsRequest, addrBook deployment.AddressBook) (*ConfigureContractsResponse, error) { - registryChain, ok := req.Env.Chains[req.RegistryChainSel] +func GetRegistryContract(e *deployment.Environment, registryChainSel uint64, addrBook deployment.AddressBook) (*kcr.CapabilitiesRegistry, deployment.Chain, error) { + registryChain, ok := e.Chains[registryChainSel] if !ok { - return nil, fmt.Errorf("chain %d not found in environment", req.RegistryChainSel) + return nil, deployment.Chain{}, fmt.Errorf("chain %d not found in environment", registryChainSel) } - contractSetsResp, err := GetContractSets(req.Env.Logger, &GetContractSetsRequest{ - Chains: req.Env.Chains, + contractSetsResp, err := GetContractSets(e.Logger, &GetContractSetsRequest{ + Chains: e.Chains, AddressBook: addrBook, }) if err != nil { - return nil, fmt.Errorf("failed to get contract sets: %w", err) - } - - donInfos, err := DonInfos(req.Dons, req.Env.Offchain) - if err != nil { - return nil, fmt.Errorf("failed to get don infos: %w", err) + return nil, deployment.Chain{}, fmt.Errorf("failed to get contract sets: %w", err) } // ensure registry is deployed and get the registry contract and chain var registry *kcr.CapabilitiesRegistry - registryChainContracts, ok := contractSetsResp.ContractSets[req.RegistryChainSel] + registryChainContracts, ok := contractSetsResp.ContractSets[registryChainSel] if !ok { - return nil, fmt.Errorf("failed to deploy registry chain contracts. expected chain %d", req.RegistryChainSel) + return nil, deployment.Chain{}, fmt.Errorf("failed to deploy registry chain contracts. expected chain %d", registryChainSel) } registry = registryChainContracts.CapabilitiesRegistry if registry == nil { - return nil, fmt.Errorf("no registry contract found") + return nil, deployment.Chain{}, fmt.Errorf("no registry contract found") + } + e.Logger.Debugf("registry contract address: %s, chain %d", registry.Address().String(), registryChainSel) + return registry, registryChain, nil +} + +// ConfigureRegistry configures the registry contract with the given DONS and their capabilities +// the address book is required to contain the addresses of the deployed registry contract +func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureContractsRequest, addrBook deployment.AddressBook) (*ConfigureContractsResponse, error) { + donInfos, err := DonInfos(req.Dons, req.Env.Offchain) + if err != nil { + return nil, fmt.Errorf("failed to get don infos: %w", err) } - lggr.Debugf("registry contract address: %s, chain %d", registry.Address().String(), req.RegistryChainSel) // all the subsequent calls to the registry are in terms of nodes // compute the mapping of dons to their nodes for reuse in various registry calls @@ -220,22 +222,22 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon } // register capabilities - capabilitiesResp, err := registerCapabilities(lggr, registerCapabilitiesRequest{ - chain: registryChain, - registry: registry, - donToCapabilities: donToCapabilities, + capabilitiesResp, err := RegisterCapabilities(lggr, RegisterCapabilitiesRequest{ + Env: req.Env, + RegistryChainSelector: req.RegistryChainSel, + DonToCapabilities: donToCapabilities, }) if err != nil { return nil, fmt.Errorf("failed to register capabilities: %w", err) } - lggr.Infow("registered capabilities", "capabilities", capabilitiesResp.donToCapabilities) + lggr.Infow("registered capabilities", "capabilities", capabilitiesResp.DonToCapabilities) // register node operators nopsList := maps.Keys(nopsToNodeIDs) nopsResp, err := RegisterNOPS(ctx, lggr, RegisterNOPSRequest{ - Chain: registryChain, - Registry: registry, - Nops: nopsList, + Env: req.Env, + RegistryChainSelector: req.RegistryChainSel, + Nops: nopsList, }) if err != nil { return nil, fmt.Errorf("failed to register node operators: %w", err) @@ -243,13 +245,13 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon lggr.Infow("registered node operators", "nops", nopsResp.Nops) // register nodes - nodesResp, err := registerNodes(lggr, ®isterNodesRequest{ - registry: registry, - chain: registryChain, - nopToNodeIDs: nopsToNodeIDs, - donToNodes: donToNodes, - donToCapabilities: capabilitiesResp.donToCapabilities, - nops: nopsResp.Nops, + nodesResp, err := RegisterNodes(lggr, &RegisterNodesRequest{ + Env: req.Env, + RegistryChainSelector: req.RegistryChainSel, + NopToNodeIDs: nopsToNodeIDs, + DonToNodes: donToNodes, + DonToCapabilities: capabilitiesResp.DonToCapabilities, + Nops: nopsResp.Nops, }) if err != nil { return nil, fmt.Errorf("failed to register nodes: %w", err) @@ -258,60 +260,51 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon // TODO: annotate nodes with node_operator_id in JD? + donsToRegister := []DONToRegister{} + for _, don := range req.Dons { + nodes, ok := donToNodes[don.Name] + if !ok { + return nil, fmt.Errorf("nodes not found for don %s", don.Name) + } + f := don.F + if f == 0 { + // TODO: fallback to a default value for compatibility - change to error + f = uint8(len(nodes) / 3) + lggr.Warnw("F not set for don - falling back to default", "don", don.Name, "f", f) + } + donsToRegister = append(donsToRegister, DONToRegister{ + Name: don.Name, + F: f, + Nodes: nodes, + }) + } + + nodeIdToP2PID := map[string][32]byte{} + for nodeID, params := range nodesResp.nodeIDToParams { + nodeIdToP2PID[nodeID] = params.P2pId + } // register DONS - donsResp, err := registerDons(lggr, registerDonsRequest{ - registry: registry, - chain: registryChain, - nodeIDToParams: nodesResp.nodeIDToParams, - donToCapabilities: capabilitiesResp.donToCapabilities, - donToNodes: donToNodes, + donsResp, err := RegisterDons(lggr, RegisterDonsRequest{ + Env: req.Env, + RegistryChainSelector: req.RegistryChainSel, + NodeIDToP2PID: nodeIdToP2PID, + DonToCapabilities: capabilitiesResp.DonToCapabilities, + DonsToRegister: donsToRegister, }) if err != nil { return nil, fmt.Errorf("failed to register DONS: %w", err) } - lggr.Infow("registered DONs", "dons", len(donsResp.donInfos)) + lggr.Infow("registered DONs", "dons", len(donsResp.DonInfos)) return &ConfigureContractsResponse{ - Changeset: &deployment.ChangesetOutput{ - AddressBook: addrBook, - }, - DonInfos: donsResp.donInfos, + Changeset: &deployment.ChangesetOutput{}, // no new addresses, proposals etc + DonInfos: donsResp.DonInfos, }, nil } -// ConfigureForwardContracts configures the forwarder contracts on all chains for the given DONS -// the address book is required to contain the an address of the deployed forwarder contract for every chain in the environment -func ConfigureForwardContracts(env *deployment.Environment, dons []RegisteredDon, addrBook deployment.AddressBook) error { - contractSetsResp, err := GetContractSets(env.Logger, &GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: addrBook, - }) - if err != nil { - return fmt.Errorf("failed to get contract sets: %w", err) - } - - // configure forwarders on all chains - for _, chain := range env.Chains { - // get the forwarder contract for the chain - contracts, ok := contractSetsResp.ContractSets[chain.Selector] - if !ok { - return fmt.Errorf("failed to get contract set for chain %d", chain.Selector) - } - fwrd := contracts.Forwarder - if fwrd == nil { - return fmt.Errorf("no forwarder contract found for chain %d", chain.Selector) - } - - err := configureForwarder(env.Logger, chain, fwrd, dons) - if err != nil { - return fmt.Errorf("failed to configure forwarder for chain selector %d: %w", chain.Selector, err) - } - } - return nil -} - +// Depreciated: use changeset.ConfigureOCR3Contract instead // ocr3 contract on the registry chain for the wf dons -func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []RegisteredDon, addrBook deployment.AddressBook, cfg *OracleConfigWithSecrets) error { +func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []RegisteredDon, cfg *OracleConfig) error { registryChain, ok := env.Chains[chainSel] if !ok { return fmt.Errorf("chain %d not found in environment", chainSel) @@ -319,7 +312,7 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons [] contractSetsResp, err := GetContractSets(env.Logger, &GetContractSetsRequest{ Chains: env.Chains, - AddressBook: addrBook, + AddressBook: env.ExistingAddresses, }) if err != nil { return fmt.Errorf("failed to get contract sets: %w", err) @@ -340,10 +333,12 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons [] } _, err := configureOCR3contract(configureOCR3Request{ - cfg: cfg, - chain: registryChain, - contract: contract, - nodes: don.Nodes, + cfg: cfg, + chain: registryChain, + contract: contract, + nodes: don.Nodes, + contractSet: &contracts, + ocrSecrets: env.OCRSecrets, }) if err != nil { return fmt.Errorf("failed to configure OCR3 contract for don %s: %w", don.Name, err) @@ -354,15 +349,19 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons [] type ConfigureOCR3Resp struct { OCR2OracleConfig + Proposal *timelock.MCMSWithTimelockProposal } type ConfigureOCR3Config struct { ChainSel uint64 NodeIDs []string - OCR3Config *OracleConfigWithSecrets + OCR3Config *OracleConfig DryRun bool + + UseMCMS bool } +// Depreciated: use changeset.ConfigureOCR3Contract instead func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3Config) (*ConfigureOCR3Resp, error) { prefix := "" if cfg.DryRun { @@ -393,29 +392,33 @@ func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3C return nil, err } r, err := configureOCR3contract(configureOCR3Request{ - cfg: cfg.OCR3Config, - chain: registryChain, - contract: contract, - nodes: nodes, - dryRun: cfg.DryRun, + cfg: cfg.OCR3Config, + chain: registryChain, + contract: contract, + nodes: nodes, + dryRun: cfg.DryRun, + contractSet: &contracts, + useMCMS: cfg.UseMCMS, + ocrSecrets: env.OCRSecrets, }) if err != nil { return nil, err } return &ConfigureOCR3Resp{ OCR2OracleConfig: r.ocrConfig, + Proposal: r.proposal, }, nil } -type registerCapabilitiesRequest struct { - chain deployment.Chain - registry *kcr.CapabilitiesRegistry - donToCapabilities map[string][]kcr.CapabilitiesRegistryCapability +type RegisterCapabilitiesRequest struct { + Env *deployment.Environment + RegistryChainSelector uint64 + DonToCapabilities map[string][]kcr.CapabilitiesRegistryCapability } -type registerCapabilitiesResponse struct { - donToCapabilities map[string][]RegisteredCapability +type RegisterCapabilitiesResponse struct { + DonToCapabilities map[string][]RegisteredCapability } type RegisteredCapability struct { @@ -423,25 +426,44 @@ type RegisteredCapability struct { ID [32]byte } -// registerCapabilities add computes the capability id, adds it to the registry and associates the registered capabilities with appropriate don(s) -func registerCapabilities(lggr logger.Logger, req registerCapabilitiesRequest) (*registerCapabilitiesResponse, error) { - if len(req.donToCapabilities) == 0 { +func FromCapabilitiesRegistryCapability(cap *kcr.CapabilitiesRegistryCapability, e deployment.Environment, registryChainSelector uint64) (*RegisteredCapability, error) { + registry, _, err := GetRegistryContract(&e, registryChainSelector, e.ExistingAddresses) + if err != nil { + return nil, fmt.Errorf("failed to get registry: %w", err) + } + id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.LabelledName, cap.Version) + if err != nil { + return nil, fmt.Errorf("failed to call GetHashedCapabilityId for capability %v: %w", cap, err) + } + return &RegisteredCapability{ + CapabilitiesRegistryCapability: *cap, + ID: id, + }, nil +} + +// RegisterCapabilities add computes the capability id, adds it to the registry and associates the registered capabilities with appropriate don(s) +func RegisterCapabilities(lggr logger.Logger, req RegisterCapabilitiesRequest) (*RegisterCapabilitiesResponse, error) { + if len(req.DonToCapabilities) == 0 { return nil, fmt.Errorf("no capabilities to register") } - lggr.Infow("registering capabilities...", "len", len(req.donToCapabilities)) - resp := ®isterCapabilitiesResponse{ - donToCapabilities: make(map[string][]RegisteredCapability), + registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSelector, req.Env.ExistingAddresses) + if err != nil { + return nil, fmt.Errorf("failed to get registry: %w", err) + } + lggr.Infow("registering capabilities...", "len", len(req.DonToCapabilities)) + resp := &RegisterCapabilitiesResponse{ + DonToCapabilities: make(map[string][]RegisteredCapability), } // capability could be hosted on multiple dons. need to deduplicate uniqueCaps := make(map[kcr.CapabilitiesRegistryCapability][32]byte) - for don, caps := range req.donToCapabilities { + for don, caps := range req.DonToCapabilities { var registerCaps []RegisteredCapability for _, cap := range caps { id, ok := uniqueCaps[cap] if !ok { var err error - id, err = req.registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.LabelledName, cap.Version) + id, err = registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.LabelledName, cap.Version) if err != nil { return nil, fmt.Errorf("failed to call GetHashedCapabilityId for capability %v: %w", cap, err) } @@ -454,7 +476,7 @@ func registerCapabilities(lggr logger.Logger, req registerCapabilitiesRequest) ( lggr.Debugw("hashed capability id", "capability", cap, "id", id) registerCaps = append(registerCaps, registerCap) } - resp.donToCapabilities[don] = registerCaps + resp.DonToCapabilities[don] = registerCaps } var capabilities []kcr.CapabilitiesRegistryCapability @@ -462,7 +484,7 @@ func registerCapabilities(lggr logger.Logger, req registerCapabilitiesRequest) ( capabilities = append(capabilities, cap) } - err := AddCapabilities(lggr, req.registry, req.chain, capabilities) + err = AddCapabilities(lggr, registry, registryChain, capabilities) if err != nil { return nil, fmt.Errorf("failed to add capabilities: %w", err) } @@ -470,9 +492,9 @@ func registerCapabilities(lggr logger.Logger, req registerCapabilitiesRequest) ( } type RegisterNOPSRequest struct { - Chain deployment.Chain - Registry *kcr.CapabilitiesRegistry - Nops []kcr.CapabilitiesRegistryNodeOperator + Env *deployment.Environment + RegistryChainSelector uint64 + Nops []kcr.CapabilitiesRegistryNodeOperator } type RegisterNOPSResponse struct { @@ -480,8 +502,12 @@ type RegisterNOPSResponse struct { } func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSRequest) (*RegisterNOPSResponse, error) { + registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSelector, req.Env.ExistingAddresses) + if err != nil { + return nil, fmt.Errorf("failed to get registry: %w", err) + } lggr.Infow("registering node operators...", "len", len(req.Nops)) - existingNops, err := req.Registry.GetNodeOperators(&bind.CallOpts{}) + existingNops, err := registry.GetNodeOperators(&bind.CallOpts{}) if err != nil { return nil, err } @@ -510,19 +536,19 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque lggr.Debug("no new node operators to register") return resp, nil } - tx, err := req.Registry.AddNodeOperators(req.Chain.DeployerKey, nops) + tx, err := registry.AddNodeOperators(registryChain.DeployerKey, nops) if err != nil { err = DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call AddNodeOperators: %w", err) } // for some reason that i don't understand, the confirm must be called before the WaitMined or the latter will hang // (at least for a simulated backend chain) - _, err = req.Chain.Confirm(tx) + _, err = registryChain.Confirm(tx) if err != nil { return nil, fmt.Errorf("failed to confirm AddNodeOperators confirm transaction %s: %w", tx.Hash().String(), err) } - receipt, err := bind.WaitMined(ctx, req.Chain.Client, tx) + receipt, err := bind.WaitMined(ctx, registryChain.Client, tx) if err != nil { return nil, fmt.Errorf("failed to mine AddNodeOperators confirm transaction %s: %w", tx.Hash().String(), err) } @@ -530,7 +556,7 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque return nil, fmt.Errorf("expected %d log entries for AddNodeOperators, got %d", len(nops), len(receipt.Logs)) } for i, log := range receipt.Logs { - o, err := req.Registry.ParseNodeOperatorAdded(*log) + o, err := registry.ParseNodeOperatorAdded(*log) if err != nil { return nil, fmt.Errorf("failed to parse log %d for operator added: %w", i, err) } @@ -599,34 +625,39 @@ func DecodeErr(encodedABI string, err error) error { } // register nodes -type registerNodesRequest struct { - registry *kcr.CapabilitiesRegistry - chain deployment.Chain - nopToNodeIDs map[kcr.CapabilitiesRegistryNodeOperator][]string - donToNodes map[string][]deployment.Node - donToCapabilities map[string][]RegisteredCapability - nops []*kcr.CapabilitiesRegistryNodeOperatorAdded -} -type registerNodesResponse struct { +type RegisterNodesRequest struct { + Env *deployment.Environment + RegistryChainSelector uint64 + NopToNodeIDs map[kcr.CapabilitiesRegistryNodeOperator][]string + DonToNodes map[string][]deployment.Node + DonToCapabilities map[string][]RegisteredCapability + Nops []*kcr.CapabilitiesRegistryNodeOperatorAdded +} +type RegisterNodesResponse struct { nodeIDToParams map[string]kcr.CapabilitiesRegistryNodeParams } // registerNodes registers the nodes with the registry. it assumes that the deployer key in the Chain // can sign the transactions update the contract state // TODO: 467 refactor to support MCMS. Specifically need to separate the call data generation from the actual contract call -func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNodesResponse, error) { +func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNodesResponse, error) { + registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSelector, req.Env.ExistingAddresses) + if err != nil { + return nil, fmt.Errorf("failed to get registry: %w", err) + } + var count int - for _, nodes := range req.nopToNodeIDs { + for _, nodes := range req.NopToNodeIDs { count += len(nodes) } lggr.Infow("registering nodes...", "len", count) nodeToRegisterNop := make(map[string]*kcr.CapabilitiesRegistryNodeOperatorAdded) - for _, nop := range req.nops { + for _, nop := range req.Nops { n := kcr.CapabilitiesRegistryNodeOperator{ Name: nop.Name, Admin: nop.Admin, } - nodeIDs := req.nopToNodeIDs[n] + nodeIDs := req.NopToNodeIDs[n] for _, nodeID := range nodeIDs { _, exists := nodeToRegisterNop[nodeID] if !exists { @@ -636,7 +667,7 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode } // TODO: deduplicate everywhere - registryChainID, err := chainsel.ChainIdFromSelector(req.chain.Selector) + registryChainID, err := chainsel.ChainIdFromSelector(registryChain.Selector) if err != nil { return nil, err } @@ -646,10 +677,10 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode } nodeIDToParams := make(map[string]kcr.CapabilitiesRegistryNodeParams) - for don, nodes := range req.donToNodes { - caps, ok := req.donToCapabilities[don] + for don, nodes := range req.DonToNodes { + caps, ok := req.DonToCapabilities[don] if !ok { - return nil, fmt.Errorf("capabilities not found for node operator %s", don) + return nil, fmt.Errorf("capabilities not found for don %s", don) } var hashedCapabilityIds [][32]byte for _, cap := range caps { @@ -670,7 +701,7 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode if !ok { evmCC, exists := n.SelToOCRConfig[registryChainDetails] if !exists { - return nil, fmt.Errorf("config for selector not found on node: %v", req.chain.Selector) + return nil, fmt.Errorf("config for selector %v not found on node (id: %s, name: %s)", registryChain.Selector, n.NodeID, n.Name) } var signer [32]byte copy(signer[:], evmCC.OnchainPublicKey) @@ -708,8 +739,8 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode for _, v := range nodeIDToParams { uniqueNodeParams = append(uniqueNodeParams, v) } - lggr.Debugw("unique node params to add", "count", len(uniqueNodeParams)) - tx, err := req.registry.AddNodes(req.chain.DeployerKey, uniqueNodeParams) + lggr.Debugw("unique node params to add", "count", len(uniqueNodeParams), "params", uniqueNodeParams) + tx, err := registry.AddNodes(registryChain.DeployerKey, uniqueNodeParams) if err != nil { err = DecodeErr(kcr.CapabilitiesRegistryABI, err) // no typed errors in the abi, so we have to do string matching @@ -719,7 +750,7 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode } lggr.Warn("nodes already exist, falling back to 1-by-1") for _, singleNodeParams := range uniqueNodeParams { - tx, err = req.registry.AddNodes(req.chain.DeployerKey, []kcr.CapabilitiesRegistryNodeParams{singleNodeParams}) + tx, err = registry.AddNodes(registryChain.DeployerKey, []kcr.CapabilitiesRegistryNodeParams{singleNodeParams}) if err != nil { err = DecodeErr(kcr.CapabilitiesRegistryABI, err) if strings.Contains(err.Error(), "NodeAlreadyExists") { @@ -729,7 +760,7 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode return nil, fmt.Errorf("failed to call AddNode for node with p2pid %v: %w", singleNodeParams.P2pId, err) } // 1-by-1 tx is pending and we need to wait for it to be mined - _, err = req.chain.Confirm(tx) + _, err = registryChain.Confirm(tx) if err != nil { return nil, fmt.Errorf("failed to confirm AddNode of p2pid node %v transaction %s: %w", singleNodeParams.P2pId, tx.Hash().String(), err) } @@ -737,27 +768,33 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode } } else { // the bulk add tx is pending and we need to wait for it to be mined - _, err = req.chain.Confirm(tx) + _, err = registryChain.Confirm(tx) if err != nil { return nil, fmt.Errorf("failed to confirm AddNode confirm transaction %s: %w", tx.Hash().String(), err) } } - return ®isterNodesResponse{ + return &RegisterNodesResponse{ nodeIDToParams: nodeIDToParams, }, nil } -type registerDonsRequest struct { - registry *kcr.CapabilitiesRegistry - chain deployment.Chain +type DONToRegister struct { + Name string + F uint8 + Nodes []deployment.Node +} + +type RegisterDonsRequest struct { + Env *deployment.Environment + RegistryChainSelector uint64 - nodeIDToParams map[string]kcr.CapabilitiesRegistryNodeParams - donToCapabilities map[string][]RegisteredCapability - donToNodes map[string][]deployment.Node + NodeIDToP2PID map[string][32]byte + DonToCapabilities map[string][]RegisteredCapability + DonsToRegister []DONToRegister } -type registerDonsResponse struct { - donInfos map[string]kcr.CapabilitiesRegistryDONInfo +type RegisterDonsResponse struct { + DonInfos map[string]kcr.CapabilitiesRegistryDONInfo } func sortedHash(p2pids [][32]byte) string { @@ -771,14 +808,18 @@ func sortedHash(p2pids [][32]byte) string { return hex.EncodeToString(sha256Hash.Sum(nil)) } -func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsResponse, error) { - lggr.Infow("registering DONs...", "len", len(req.donToNodes)) +func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsResponse, error) { + registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSelector, req.Env.ExistingAddresses) + if err != nil { + return nil, fmt.Errorf("failed to get registry: %w", err) + } + lggr.Infow("registering DONs...", "len", len(req.DonsToRegister)) // track hash of sorted p2pids to don name because the registry return value does not include the don name // and we need to map it back to the don name to access the other mapping data such as the don's capabilities & nodes p2pIdsToDon := make(map[string]string) var addedDons = 0 - donInfos, err := req.registry.GetDONs(&bind.CallOpts{}) + donInfos, err := registry.GetDONs(&bind.CallOpts{}) if err != nil { err = DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call GetDONs: %w", err) @@ -789,30 +830,30 @@ func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsRes } lggr.Infow("fetched existing DONs...", "len", len(donInfos), "lenByNodesHash", len(existingDONs)) - for don, nodes := range req.donToNodes { + for _, don := range req.DonsToRegister { var p2pIds [][32]byte - for _, n := range nodes { + for _, n := range don.Nodes { if n.IsBootstrap { continue } - params, ok := req.nodeIDToParams[n.NodeID] + p2pID, ok := req.NodeIDToP2PID[n.NodeID] if !ok { return nil, fmt.Errorf("node params not found for non-bootstrap node %s", n.NodeID) } - p2pIds = append(p2pIds, params.P2pId) + p2pIds = append(p2pIds, p2pID) } p2pSortedHash := sortedHash(p2pIds) - p2pIdsToDon[p2pSortedHash] = don + p2pIdsToDon[p2pSortedHash] = don.Name if _, ok := existingDONs[p2pSortedHash]; ok { lggr.Debugw("don already exists, ignoring", "don", don, "p2p sorted hash", p2pSortedHash) continue } - caps, ok := req.donToCapabilities[don] + caps, ok := req.DonToCapabilities[don.Name] if !ok { - return nil, fmt.Errorf("capabilities not found for node operator %s", don) + return nil, fmt.Errorf("capabilities not found for DON %s", don.Name) } wfSupported := false var cfgs []kcr.CapabilitiesRegistryCapabilityConfiguration @@ -832,17 +873,16 @@ func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsRes }) } - f := len(p2pIds) / 3 // assuming n=3f+1. TODO should come for some config. - tx, err := req.registry.AddDON(req.chain.DeployerKey, p2pIds, cfgs, true, wfSupported, uint8(f)) + tx, err := registry.AddDON(registryChain.DeployerKey, p2pIds, cfgs, true, wfSupported, don.F) if err != nil { err = DecodeErr(kcr.CapabilitiesRegistryABI, err) - return nil, fmt.Errorf("failed to call AddDON for don '%s' p2p2Id hash %s capability %v: %w", don, p2pSortedHash, cfgs, err) + return nil, fmt.Errorf("failed to call AddDON for don '%s' p2p2Id hash %s capability %v: %w", don.Name, p2pSortedHash, cfgs, err) } - _, err = req.chain.Confirm(tx) + _, err = registryChain.Confirm(tx) if err != nil { - return nil, fmt.Errorf("failed to confirm AddDON transaction %s for don %s: %w", tx.Hash().String(), don, err) + return nil, fmt.Errorf("failed to confirm AddDON transaction %s for don %s: %w", tx.Hash().String(), don.Name, err) } - lggr.Debugw("registered DON", "don", don, "p2p sorted hash", p2pSortedHash, "cgs", cfgs, "wfSupported", wfSupported, "f", f) + lggr.Debugw("registered DON", "don", don.Name, "p2p sorted hash", p2pSortedHash, "cgs", cfgs, "wfSupported", wfSupported, "f", don.F) addedDons++ } lggr.Debugf("Registered all DONs (new=%d), waiting for registry to update", addedDons) @@ -852,7 +892,7 @@ func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsRes foundAll := false for i := 0; i < 10; i++ { lggr.Debugw("attempting to get DONs from registry", "attempt#", i) - donInfos, err = req.registry.GetDONs(&bind.CallOpts{}) + donInfos, err = registry.GetDONs(&bind.CallOpts{}) if !containsAllDONs(donInfos, p2pIdsToDon) { lggr.Debugw("some expected dons not registered yet, re-checking after a delay ...") time.Sleep(2 * time.Second) @@ -869,8 +909,8 @@ func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsRes return nil, fmt.Errorf("did not find all desired DONS") } - resp := registerDonsResponse{ - donInfos: make(map[string]kcr.CapabilitiesRegistryDONInfo), + resp := RegisterDonsResponse{ + DonInfos: make(map[string]kcr.CapabilitiesRegistryDONInfo), } for i, donInfo := range donInfos { donName, ok := p2pIdsToDon[sortedHash(donInfo.NodeP2PIds)] @@ -879,7 +919,7 @@ func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsRes continue } lggr.Debugw("adding don info to the reponse (keyed by DON name)", "don", donName) - resp.donInfos[donName] = donInfos[i] + resp.DonInfos[donName] = donInfos[i] } return &resp, nil } @@ -898,27 +938,67 @@ func containsAllDONs(donInfos []kcr.CapabilitiesRegistryDONInfo, p2pIdsToDon map // configureForwarder sets the config for the forwarder contract on the chain for all Dons that accept workflows // dons that don't accept workflows are not registered with the forwarder -func configureForwarder(lggr logger.Logger, chain deployment.Chain, fwdr *kf.KeystoneForwarder, dons []RegisteredDon) error { - if fwdr == nil { - return errors.New("nil forwarder contract") - } +func configureForwarder(lggr logger.Logger, chain deployment.Chain, contractSet ContractSet, dons []RegisteredDon, useMCMS bool) ([]timelock.MCMSWithTimelockProposal, error) { + if contractSet.Forwarder == nil { + return nil, errors.New("nil forwarder contract") + } + var ( + fwdr = contractSet.Forwarder + proposals []timelock.MCMSWithTimelockProposal + ) for _, dn := range dons { if !dn.Info.AcceptsWorkflows { continue } ver := dn.Info.ConfigCount // note config count on the don info is the version on the forwarder - signers := dn.signers(chainsel.FamilyEVM) - tx, err := fwdr.SetConfig(chain.DeployerKey, dn.Info.Id, ver, dn.Info.F, signers) - if err != nil { - err = DecodeErr(kf.KeystoneForwarderABI, err) - return fmt.Errorf("failed to call SetConfig for forwarder %s on chain %d: %w", fwdr.Address().String(), chain.Selector, err) + signers := dn.Signers(chainsel.FamilyEVM) + txOpts := chain.DeployerKey + if useMCMS { + txOpts = deployment.SimTransactOpts() } - _, err = chain.Confirm(tx) + tx, err := fwdr.SetConfig(txOpts, dn.Info.Id, ver, dn.Info.F, signers) if err != nil { err = DecodeErr(kf.KeystoneForwarderABI, err) - return fmt.Errorf("failed to confirm SetConfig for forwarder %s: %w", fwdr.Address().String(), err) + return nil, fmt.Errorf("failed to call SetConfig for forwarder %s on chain %d: %w", fwdr.Address().String(), chain.Selector, err) + } + if !useMCMS { + _, err = chain.Confirm(tx) + if err != nil { + err = DecodeErr(kf.KeystoneForwarderABI, err) + return nil, fmt.Errorf("failed to confirm SetConfig for forwarder %s: %w", fwdr.Address().String(), err) + } + } else { + // create the mcms proposals + ops := timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chain.Selector), + Batch: []mcms.Operation{ + { + To: fwdr.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + } + timelocksPerChain := map[uint64]common.Address{ + chain.Selector: contractSet.Timelock.Address(), + } + proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ + chain.Selector: contractSet.ProposerMcm, + } + + proposal, err := proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + []timelock.BatchChainOperation{ops}, + "proposal to set forward config", + 0, + ) + if err != nil { + return nil, fmt.Errorf("failed to build proposal: %w", err) + } + proposals = append(proposals, *proposal) } lggr.Debugw("configured forwarder", "forwarder", fwdr.Address().String(), "donId", dn.Info.Id, "version", ver, "f", dn.Info.F, "signers", signers) } - return nil + return proposals, nil } diff --git a/deployment/keystone/deploy_test.go b/deployment/keystone/deploy_test.go index e446405944c..eb167ed60fb 100644 --- a/deployment/keystone/deploy_test.go +++ b/deployment/keystone/deploy_test.go @@ -9,8 +9,10 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/clo" "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" @@ -19,192 +21,9 @@ import ( kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/stretchr/testify/assert" - "github.com/test-go/testify/require" - "go.uber.org/zap/zapcore" - "golang.org/x/exp/maps" + "github.com/stretchr/testify/require" ) -func TestDeploy(t *testing.T) { - lggr := logger.Test(t) - - // sepolia; all nodes are on the this chain - sepoliaChainId := uint64(11155111) - sepoliaArbitrumChainId := uint64(421614) - - sepoliaChainSel, err := chainsel.SelectorFromChainId(sepoliaChainId) - require.NoError(t, err) - // sepoliaArbitrumChainSel, err := chainsel.SelectorFromChainId(sepoliaArbitrumChainId) - // require.NoError(t, err) - // aptos-testnet - aptosChainSel := chainsel.AptosChainIdToChainSelector()[2] - - crConfig := deployment.CapabilityRegistryConfig{ - EVMChainID: sepoliaChainId, - Contract: [20]byte{}, - } - - evmChains := memory.NewMemoryChainsWithChainIDs(t, []uint64{sepoliaChainId, sepoliaArbitrumChainId}) - aptosChain := memory.NewMemoryChain(t, aptosChainSel) - - wfChains := map[uint64]deployment.Chain{} - wfChains[sepoliaChainSel] = evmChains[sepoliaChainSel] - wfChains[aptosChainSel] = aptosChain - wfNodes := memory.NewNodes(t, zapcore.InfoLevel, wfChains, 4, 0, crConfig) - require.Len(t, wfNodes, 4) - - cwNodes := memory.NewNodes(t, zapcore.InfoLevel, evmChains, 4, 0, crConfig) - - assetChains := map[uint64]deployment.Chain{} - assetChains[sepoliaChainSel] = evmChains[sepoliaChainSel] - assetNodes := memory.NewNodes(t, zapcore.InfoLevel, assetChains, 4, 0, crConfig) - require.Len(t, assetNodes, 4) - - // TODO: partition nodes into multiple nops - - wfDon := keystone.DonCapabilities{ - Name: keystone.WFDonName, - Nops: []keystone.NOP{ - { - Name: "nop 1", - Nodes: maps.Keys(wfNodes), - }, - }, - Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.OCR3Cap}, - } - cwDon := keystone.DonCapabilities{ - Name: keystone.TargetDonName, - Nops: []keystone.NOP{ - { - Name: "nop 2", - Nodes: maps.Keys(cwNodes), - }, - }, - Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.WriteChainCap}, - } - assetDon := keystone.DonCapabilities{ - Name: keystone.StreamDonName, - Nops: []keystone.NOP{ - { - Name: "nop 3", - Nodes: maps.Keys(assetNodes), - }, - }, - Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.StreamTriggerCap}, - } - - allChains := make(map[uint64]deployment.Chain) - maps.Copy(allChains, evmChains) - // allChains[aptosChainSel] = aptosChain - - allNodes := make(map[string]memory.Node) - maps.Copy(allNodes, wfNodes) - maps.Copy(allNodes, cwNodes) - maps.Copy(allNodes, assetNodes) - env := memory.NewMemoryEnvironmentFromChainsNodes(t, lggr, allChains, allNodes) - - var ocr3Config = keystone.OracleConfigWithSecrets{ - OracleConfig: keystone.OracleConfig{ - MaxFaultyOracles: len(wfNodes) / 3, - }, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), - } - - ctx := tests.Context(t) - // explicitly deploy the contracts - cs, err := keystone.DeployContracts(lggr, &env, sepoliaChainSel) - require.NoError(t, err) - env.ExistingAddresses = cs.AddressBook - deployReq := keystone.ConfigureContractsRequest{ - RegistryChainSel: sepoliaChainSel, - Env: &env, - OCR3Config: &ocr3Config, - Dons: []keystone.DonCapabilities{wfDon, cwDon, assetDon}, - DoContractDeploy: false, - } - deployResp, err := keystone.ConfigureContracts(ctx, lggr, deployReq) - require.NoError(t, err) - ad := deployResp.Changeset.AddressBook - addrs, err := ad.Addresses() - require.NoError(t, err) - lggr.Infow("Deployed Keystone contracts", "address book", addrs) - - // all contracts on home chain - homeChainAddrs, err := ad.AddressesForChain(sepoliaChainSel) - require.NoError(t, err) - require.Len(t, homeChainAddrs, 3) - // only forwarder on non-home chain - for sel := range env.Chains { - chainAddrs, err := ad.AddressesForChain(sel) - require.NoError(t, err) - if sel != sepoliaChainSel { - require.Len(t, chainAddrs, 1) - } else { - require.Len(t, chainAddrs, 3) - } - containsForwarder := false - for _, tv := range chainAddrs { - if tv.Type == keystone.KeystoneForwarder { - containsForwarder = true - break - } - } - require.True(t, containsForwarder, "no forwarder found in %v on chain %d for target don", chainAddrs, sel) - } - req := &keystone.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: ad, - } - - contractSetsResp, err := keystone.GetContractSets(lggr, req) - require.NoError(t, err) - require.Len(t, contractSetsResp.ContractSets, len(env.Chains)) - // check the registry - regChainContracts, ok := contractSetsResp.ContractSets[sepoliaChainSel] - require.True(t, ok) - gotRegistry := regChainContracts.CapabilitiesRegistry - require.NotNil(t, gotRegistry) - // contract reads - gotDons, err := gotRegistry.GetDONs(&bind.CallOpts{}) - if err != nil { - err = keystone.DecodeErr(kcr.CapabilitiesRegistryABI, err) - require.Fail(t, fmt.Sprintf("failed to get Dons from registry at %s: %s", gotRegistry.Address().String(), err)) - } - require.NoError(t, err) - assert.Len(t, gotDons, len(deployReq.Dons)) - - for n, info := range deployResp.DonInfos { - found := false - for _, gdon := range gotDons { - if gdon.Id == info.Id { - found = true - assert.EqualValues(t, info, gdon) - break - } - } - require.True(t, found, "don %s not found in registry", n) - } - // check the forwarder - for _, cs := range contractSetsResp.ContractSets { - forwarder := cs.Forwarder - require.NotNil(t, forwarder) - // any read to ensure that the contract is deployed correctly - _, err := forwarder.Owner(&bind.CallOpts{}) - require.NoError(t, err) - // TODO expand this test; there is no get method on the forwarder so unclear how to test it - } - // check the ocr3 contract - for chainSel, cs := range contractSetsResp.ContractSets { - if chainSel != sepoliaChainSel { - require.Nil(t, cs.OCR3) - continue - } - require.NotNil(t, cs.OCR3) - // any read to ensure that the contract is deployed correctly - _, err := cs.OCR3.LatestConfigDetails(&bind.CallOpts{}) - require.NoError(t, err) - } -} - // TODO: Deprecated, remove everything below that leverages CLO func nodeOperatorsToIDs(t *testing.T, nops []*models.NodeOperator) (nodeIDs []keystone.NOP) { @@ -288,6 +107,7 @@ func TestDeployCLO(t *testing.T) { Offchain: clo.NewJobClient(lggr, clo.JobClientConfig{Nops: allNops}), Chains: allChains, Logger: lggr, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), } // assume that all the nodes in the provided input nops are part of the don for _, nop := range allNops { @@ -300,16 +120,13 @@ func TestDeployCLO(t *testing.T) { registryChainSel, err := chainsel.SelectorFromChainId(11155111) require.NoError(t, err) - var ocr3Config = keystone.OracleConfigWithSecrets{ - OracleConfig: keystone.OracleConfig{ - MaxFaultyOracles: len(wfNops) / 3, - }, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + var ocr3Config = keystone.OracleConfig{ + MaxFaultyOracles: len(wfNops) / 3, } ctx := tests.Context(t) // explicitly deploy the contracts - cs, err := keystone.DeployContracts(lggr, env, registryChainSel) + cs, err := keystone.DeployContracts(env, registryChainSel) require.NoError(t, err) // Deploy successful these are now part of our env. require.NoError(t, env.ExistingAddresses.Merge(cs.AddressBook)) @@ -323,10 +140,7 @@ func TestDeployCLO(t *testing.T) { } deployResp, err := keystone.ConfigureContracts(ctx, lggr, deployReq) require.NoError(t, err) - ad := deployResp.Changeset.AddressBook - addrs, err := ad.Addresses() - require.NoError(t, err) - lggr.Infow("Deployed Keystone contracts", "address book", addrs) + ad := env.ExistingAddresses // all contracts on home chain homeChainAddrs, err := ad.AddressesForChain(registryChainSel) diff --git a/deployment/keystone/forwarder_deployer.go b/deployment/keystone/forwarder_deployer.go index b7fde675973..d7cfa7991f4 100644 --- a/deployment/keystone/forwarder_deployer.go +++ b/deployment/keystone/forwarder_deployer.go @@ -4,7 +4,9 @@ import ( "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" ) @@ -14,6 +16,13 @@ type KeystoneForwarderDeployer struct { contract *forwarder.KeystoneForwarder } +func NewKeystoneForwarderDeployer() (*KeystoneForwarderDeployer, error) { + lggr, err := logger.New() + if err != nil { + return nil, err + } + return &KeystoneForwarderDeployer{lggr: lggr}, nil +} func (c *KeystoneForwarderDeployer) deploy(req DeployRequest) (*DeployResponse, error) { est, err := estimateDeploymentGas(req.Chain.Client, forwarder.KeystoneForwarderABI) if err != nil { @@ -48,3 +57,43 @@ func (c *KeystoneForwarderDeployer) deploy(req DeployRequest) (*DeployResponse, c.contract = forwarder return resp, nil } + +type ConfigureForwarderContractsRequest struct { + Dons []RegisteredDon + + UseMCMS bool +} +type ConfigureForwarderContractsResponse struct { + Proposals []timelock.MCMSWithTimelockProposal +} + +// Depreciated: use [changeset.ConfigureForwarders] instead +// ConfigureForwardContracts configures the forwarder contracts on all chains for the given DONS +// the address book is required to contain the an address of the deployed forwarder contract for every chain in the environment +func ConfigureForwardContracts(env *deployment.Environment, req ConfigureForwarderContractsRequest) (*ConfigureForwarderContractsResponse, error) { + contractSetsResp, err := GetContractSets(env.Logger, &GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: env.ExistingAddresses, + }) + if err != nil { + return nil, fmt.Errorf("failed to get contract sets: %w", err) + } + + var allProposals []timelock.MCMSWithTimelockProposal + // configure forwarders on all chains + for _, chain := range env.Chains { + // get the forwarder contract for the chain + contracts, ok := contractSetsResp.ContractSets[chain.Selector] + if !ok { + return nil, fmt.Errorf("failed to get contract set for chain %d", chain.Selector) + } + proposals, err := configureForwarder(env.Logger, chain, contracts, req.Dons, req.UseMCMS) + if err != nil { + return nil, fmt.Errorf("failed to configure forwarder for chain selector %d: %w", chain.Selector, err) + } + allProposals = append(allProposals, proposals...) + } + return &ConfigureForwarderContractsResponse{ + Proposals: allProposals, + }, nil +} diff --git a/deployment/keystone/ocr3_deployer.go b/deployment/keystone/ocr3_deployer.go index 5f2ba34f42c..227894f7c67 100644 --- a/deployment/keystone/ocr3_deployer.go +++ b/deployment/keystone/ocr3_deployer.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" ) @@ -14,6 +15,14 @@ type OCR3Deployer struct { contract *ocr3_capability.OCR3Capability } +func NewOCR3Deployer() (*OCR3Deployer, error) { + lggr, err := logger.New() + if err != nil { + return nil, err + } + return &OCR3Deployer{lggr: lggr}, nil +} + func (c *OCR3Deployer) deploy(req DeployRequest) (*DeployResponse, error) { est, err := estimateDeploymentGas(req.Chain.Client, ocr3_capability.OCR3CapabilityABI) if err != nil { diff --git a/deployment/keystone/ocr3config.go b/deployment/keystone/ocr3config.go index a281a69ed8a..ccd738636ed 100644 --- a/deployment/keystone/ocr3config.go +++ b/deployment/keystone/ocr3config.go @@ -8,6 +8,8 @@ import ( "encoding/json" "errors" "fmt" + "math/big" + "strings" "time" "github.com/ethereum/go-ethereum/common" @@ -16,7 +18,12 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" kocr3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" @@ -24,12 +31,9 @@ import ( ) type TopLevelConfigSource struct { - OracleConfig OracleConfigWithSecrets -} -type OracleConfigWithSecrets struct { - OracleConfig - deployment.OCRSecrets `json:"-" toml:"-"` // don't spill secrets + OracleConfig OracleConfig } + type OracleConfig struct { MaxQueryLengthBytes uint32 MaxObservationLengthBytes uint32 @@ -107,10 +111,48 @@ func (c OCR2OracleConfig) MarshalJSON() ([]byte, error) { return json.Marshal(alias) } -func GenerateOCR3Config(cfg OracleConfigWithSecrets, nca []NodeKeys) (OCR2OracleConfig, error) { +func (c *OCR2OracleConfig) UnmarshalJSON(data []byte) error { + type aliasT struct { + Signers []string + Transmitters []string + F uint8 + OnchainConfig string + OffchainConfigVersion uint64 + OffchainConfig string + } + var alias aliasT + err := json.Unmarshal(data, &alias) + if err != nil { + return fmt.Errorf("failed to unmarshal OCR2OracleConfig alias: %w", err) + } + c.F = alias.F + c.OffchainConfigVersion = alias.OffchainConfigVersion + c.Signers = make([][]byte, len(alias.Signers)) + for i, signer := range alias.Signers { + c.Signers[i], err = hex.DecodeString(strings.TrimPrefix(signer, "0x")) + if err != nil { + return fmt.Errorf("failed to decode signer: %w", err) + } + } + c.Transmitters = make([]common.Address, len(alias.Transmitters)) + for i, transmitter := range alias.Transmitters { + c.Transmitters[i] = common.HexToAddress(transmitter) + } + c.OnchainConfig, err = hex.DecodeString(strings.TrimPrefix(alias.OnchainConfig, "0x")) + if err != nil { + return fmt.Errorf("failed to decode onchain config: %w", err) + } + c.OffchainConfig, err = hex.DecodeString(strings.TrimPrefix(alias.OffchainConfig, "0x")) + if err != nil { + return fmt.Errorf("failed to decode offchain config: %w", err) + } + return nil +} + +func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets deployment.OCRSecrets) (OCR2OracleConfig, error) { onchainPubKeys := [][]byte{} allPubKeys := map[string]any{} - if cfg.OCRSecrets.IsEmpty() { + if secrets.IsEmpty() { return OCR2OracleConfig{}, errors.New("OCRSecrets is required") } for _, n := range nca { @@ -192,8 +234,8 @@ func GenerateOCR3Config(cfg OracleConfigWithSecrets, nca []NodeKeys) (OCR2Oracle } signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsDeterministic( - cfg.EphemeralSk, - cfg.SharedSecret, + secrets.EphemeralSk, + secrets.SharedSecret, time.Duration(cfg.DeltaProgressMillis)*time.Millisecond, time.Duration(cfg.DeltaResendMillis)*time.Millisecond, time.Duration(cfg.DeltaInitialMillis)*time.Millisecond, @@ -240,20 +282,25 @@ func GenerateOCR3Config(cfg OracleConfigWithSecrets, nca []NodeKeys) (OCR2Oracle } type configureOCR3Request struct { - cfg *OracleConfigWithSecrets - chain deployment.Chain - contract *kocr3.OCR3Capability - nodes []deployment.Node - dryRun bool + cfg *OracleConfig + chain deployment.Chain + contract *kocr3.OCR3Capability + nodes []deployment.Node + dryRun bool + ocrSecrets deployment.OCRSecrets + + useMCMS bool + contractSet *ContractSet } func (r configureOCR3Request) generateOCR3Config() (OCR2OracleConfig, error) { nks := makeNodeKeysSlice(r.nodes, r.chain.Selector) - return GenerateOCR3Config(*r.cfg, nks) + return GenerateOCR3Config(*r.cfg, nks, r.ocrSecrets) } type configureOCR3Response struct { ocrConfig OCR2OracleConfig + proposal *timelock.MCMSWithTimelockProposal } func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, error) { @@ -265,9 +312,15 @@ func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, er return nil, fmt.Errorf("failed to generate OCR3 config: %w", err) } if req.dryRun { - return &configureOCR3Response{ocrConfig}, nil + return &configureOCR3Response{ocrConfig, nil}, nil + } + + txOpt := req.chain.DeployerKey + if req.useMCMS { + txOpt = deployment.SimTransactOpts() } - tx, err := req.contract.SetConfig(req.chain.DeployerKey, + + tx, err := req.contract.SetConfig(txOpt, ocrConfig.Signers, ocrConfig.Transmitters, ocrConfig.F, @@ -277,12 +330,45 @@ func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, er ) if err != nil { err = DecodeErr(kocr3.OCR3CapabilityABI, err) - return nil, fmt.Errorf("failed to call SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) + return nil, fmt.Errorf("failed to call SetConfig for OCR3 contract %s using mcms: %T: %w", req.contract.Address().String(), req.useMCMS, err) } - _, err = req.chain.Confirm(tx) - if err != nil { - err = DecodeErr(kocr3.OCR3CapabilityABI, err) - return nil, fmt.Errorf("failed to confirm SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) + + var proposal *timelock.MCMSWithTimelockProposal + if !req.useMCMS { + _, err = req.chain.Confirm(tx) + if err != nil { + err = DecodeErr(kocr3.OCR3CapabilityABI, err) + return nil, fmt.Errorf("failed to confirm SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) + } + } else { + ops := timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(req.chain.Selector), + Batch: []mcms.Operation{ + { + To: req.contract.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + } + timelocksPerChain := map[uint64]common.Address{ + req.chain.Selector: req.contractSet.Timelock.Address(), + } + proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ + req.chain.Selector: req.contractSet.ProposerMcm, + } + + proposal, err = proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + []timelock.BatchChainOperation{ops}, + "proposal to set ocr3 config", + 0, + ) + if err != nil { + return nil, fmt.Errorf("failed to build proposal: %w", err) + } } - return &configureOCR3Response{ocrConfig}, nil + + return &configureOCR3Response{ocrConfig, proposal}, nil } diff --git a/deployment/keystone/ocr3config_test.go b/deployment/keystone/ocr3config_test.go index 4046787724a..55fa16af68c 100644 --- a/deployment/keystone/ocr3config_test.go +++ b/deployment/keystone/ocr3config_test.go @@ -11,13 +11,14 @@ import ( "github.com/ethereum/go-ethereum/common" chain_selectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/view" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" types2 "github.com/smartcontractkit/libocr/offchainreporting2/types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" types3 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/test-go/testify/require" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/view" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) var wantOCR3Config = `{ @@ -83,13 +84,13 @@ func Test_configureOCR3Request_generateOCR3Config(t *testing.T) { var cfg OracleConfig err := json.Unmarshal([]byte(ocr3Cfg), &cfg) require.NoError(t, err) - r := configureOCR3Request{ - cfg: &OracleConfigWithSecrets{OracleConfig: cfg, OCRSecrets: deployment.XXXGenerateTestOCRSecrets()}, + cfg: &cfg, nodes: nodes, chain: deployment.Chain{ Selector: chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector, }, + ocrSecrets: deployment.XXXGenerateTestOCRSecrets(), } got, err := r.generateOCR3Config() require.NoError(t, err) diff --git a/deployment/keystone/state.go b/deployment/keystone/state.go index 68f2ab97a5d..cbf449c7f31 100644 --- a/deployment/keystone/state.go +++ b/deployment/keystone/state.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" common_v1_0 "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" "github.com/smartcontractkit/chainlink/deployment/keystone/view" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" @@ -25,11 +26,26 @@ type GetContractSetsResponse struct { } type ContractSet struct { + commonchangeset.MCMSWithTimelockState OCR3 *ocr3_capability.OCR3Capability Forwarder *forwarder.KeystoneForwarder CapabilitiesRegistry *capabilities_registry.CapabilitiesRegistry } +func (cs ContractSet) TransferableContracts() []common.Address { + var out []common.Address + if cs.OCR3 != nil { + out = append(out, cs.OCR3.Address()) + } + if cs.Forwarder != nil { + out = append(out, cs.Forwarder.Address()) + } + if cs.CapabilitiesRegistry != nil { + out = append(out, cs.CapabilitiesRegistry.Address()) + } + return out +} + func (cs ContractSet) View() (view.KeystoneChainView, error) { out := view.NewKeystoneChainView() if cs.CapabilitiesRegistry != nil { @@ -62,6 +78,11 @@ func GetContractSets(lggr logger.Logger, req *GetContractSetsRequest) (*GetContr func loadContractSet(lggr logger.Logger, chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*ContractSet, error) { var out ContractSet + mcmsWithTimelock, err := commonchangeset.MaybeLoadMCMSWithTimelockState(chain, addresses) + if err != nil { + return nil, fmt.Errorf("failed to load mcms contract: %w", err) + } + out.MCMSWithTimelockState = *mcmsWithTimelock for addr, tv := range addresses { // todo handle versions diff --git a/deployment/keystone/types.go b/deployment/keystone/types.go index b7bf636c3e2..d406487043c 100644 --- a/deployment/keystone/types.go +++ b/deployment/keystone/types.go @@ -20,10 +20,12 @@ import ( ) var ( - CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol#L392 - KeystoneForwarder deployment.ContractType = "KeystoneForwarder" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/KeystoneForwarder.sol#L90 - OCR3Capability deployment.ContractType = "OCR3Capability" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/OCR3Capability.sol#L12 - FeedConsumer deployment.ContractType = "FeedConsumer" // no type and a version in contract https://github.com/smartcontractkit/chainlink/blob/89183a8a5d22b1aeca0ade3b76d16aa84067aa57/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol#L1 + CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol#L392 + KeystoneForwarder deployment.ContractType = "KeystoneForwarder" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/KeystoneForwarder.sol#L90 + OCR3Capability deployment.ContractType = "OCR3Capability" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/OCR3Capability.sol#L12 + FeedConsumer deployment.ContractType = "FeedConsumer" // no type and a version in contract https://github.com/smartcontractkit/chainlink/blob/89183a8a5d22b1aeca0ade3b76d16aa84067aa57/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol#L1 + RBACTimelock deployment.ContractType = "RBACTimelock" // no type and a version in contract https://github.com/smartcontractkit/ccip-owner-contracts/blob/main/src/RBACTimelock.sol + ProposerManyChainMultiSig deployment.ContractType = "ProposerManyChainMultiSig" // no type and a version in contract https://github.com/smartcontractkit/ccip-owner-contracts/blob/main/src/ManyChainMultiSig.sol ) type DeployResponse struct { @@ -125,6 +127,7 @@ func (v NOP) Validate() error { // in is in a convenient form to handle the CLO representation of the nop data type DonCapabilities struct { Name string + F uint8 Nops []NOP Capabilities []kcr.CapabilitiesRegistryCapability // every capability is hosted on each nop } @@ -227,7 +230,51 @@ type RegisteredDon struct { Nodes []deployment.Node } -func (d RegisteredDon) signers(chainFamily string) []common.Address { +type RegisteredDonConfig struct { + Name string + NodeIDs []string // ids in the offchain client + RegistryChainSel uint64 +} + +func NewRegisteredDon(env deployment.Environment, cfg RegisteredDonConfig) (*RegisteredDon, error) { + // load the don info from the capabilities registry + r, err := GetContractSets(env.Logger, &GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: env.ExistingAddresses, + }) + if err != nil { + return nil, fmt.Errorf("failed to get contract sets: %w", err) + } + capReg := r.ContractSets[cfg.RegistryChainSel].CapabilitiesRegistry + + di, err := capReg.GetDONs(nil) + if err != nil { + return nil, fmt.Errorf("failed to get dons: %w", err) + } + // load the nodes from the offchain client + nodes, err := deployment.NodeInfo(cfg.NodeIDs, env.Offchain) + if err != nil { + return nil, fmt.Errorf("failed to get node info: %w", err) + } + want := sortedHash(nodes.PeerIDs()) + var don *kcr.CapabilitiesRegistryDONInfo + for i, d := range di { + got := sortedHash(d.NodeP2PIds) + if got == want { + don = &di[i] + } + } + if don == nil { + return nil, fmt.Errorf("don not found in registry") + } + return &RegisteredDon{ + Name: cfg.Name, + Info: *don, + Nodes: nodes, + }, nil +} + +func (d RegisteredDon) Signers(chainFamily string) []common.Address { sort.Slice(d.Nodes, func(i, j int) bool { return d.Nodes[i].PeerID.String() < d.Nodes[j].PeerID.String() }) diff --git a/deployment/multiclient.go b/deployment/multiclient.go index dcda07ebb0b..f1ac2f3c310 100644 --- a/deployment/multiclient.go +++ b/deployment/multiclient.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/pkg/errors" + chainselectors "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-common/pkg/logger" ) @@ -46,6 +47,7 @@ type MultiClient struct { Backups []*ethclient.Client RetryConfig RetryConfig lggr logger.Logger + chainName string } func NewMultiClient(lggr logger.Logger, rpcs []RPC, opts ...func(client *MultiClient)) (*MultiClient, error) { @@ -59,6 +61,15 @@ func NewMultiClient(lggr logger.Logger, rpcs []RPC, opts ...func(client *MultiCl if err != nil { return nil, fmt.Errorf("failed to dial ws url '%s': %w", rpc.WSURL, err) } + id, err := client.ChainID(context.Background()) + if err != nil { + return nil, fmt.Errorf("failed to get chain id: %w", err) + } + details, err := chainselectors.GetChainDetailsByChainIDAndFamily(id.String(), chainselectors.FamilyEVM) + if err != nil { + return nil, fmt.Errorf("failed to lookup chain details %w", err) + } + mc.chainName = details.ChainName clients = append(clients, client) } mc.Client = clients[0] @@ -134,11 +145,12 @@ func (mc *MultiClient) WaitMined(ctx context.Context, tx *types.Transaction) (*t func (mc *MultiClient) retryWithBackups(opName string, op func(*ethclient.Client) error) error { var err error - for _, client := range append([]*ethclient.Client{mc.Client}, mc.Backups...) { + for i, client := range append([]*ethclient.Client{mc.Client}, mc.Backups...) { err2 := retry.Do(func() error { + mc.lggr.Debugf("Trying op %s with chain %s client index %d", opName, mc.chainName, i) err = op(client) if err != nil { - mc.lggr.Warnf("retryable error '%s' for op %s with client %v", err.Error(), opName, client) + mc.lggr.Warnf("retryable error '%s' for op %s with chain %s client index %d", err.Error(), opName, mc.chainName, i) return err } return nil @@ -146,7 +158,7 @@ func (mc *MultiClient) retryWithBackups(opName string, op func(*ethclient.Client if err2 == nil { return nil } - mc.lggr.Infof("Client %v failed, trying next client", client) + mc.lggr.Infof("Client at index %d failed, trying next client chain %s", i, mc.chainName) } - return errors.Wrapf(err, "All backup clients %v failed", mc.Backups) + return errors.Wrapf(err, "All backup clients %v failed for chain %s", mc.Backups, mc.chainName) } diff --git a/deployment/multiclient_test.go b/deployment/multiclient_test.go index 0dbebbe3a6a..2e10c46e33f 100644 --- a/deployment/multiclient_test.go +++ b/deployment/multiclient_test.go @@ -1,6 +1,7 @@ package deployment import ( + "io/ioutil" "net/http" "net/http/httptest" "testing" @@ -15,20 +16,33 @@ func TestMultiClient(t *testing.T) { lggr := logger.TestLogger(t) // Expect an error if no RPCs supplied. s := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { - writer.WriteHeader(http.StatusOK) - _, err := writer.Write([]byte(`{"jsonrpc":"2.0","id":1,"result":true}`)) + b, err := ioutil.ReadAll(request.Body) require.NoError(t, err) + // TODO: Helper struct somewhere for this? + if string(b) == "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_chainId\"}" { + writer.WriteHeader(http.StatusOK) + // Respond with 1337 + _, err = writer.Write([]byte(`{"jsonrpc":"2.0","id":1,"result":"0x539"}`)) + require.NoError(t, err) + return + } else { + // Dial + writer.WriteHeader(http.StatusOK) + _, err = writer.Write([]byte(`{"jsonrpc":"2.0","id":1,"result":true}`)) + require.NoError(t, err) + } })) defer s.Close() - _, err := NewMultiClient(lggr, []RPC{}) - require.Error(t, err) - // Expect defaults to be set if not provided. mc, err := NewMultiClient(lggr, []RPC{{WSURL: s.URL}}) require.NoError(t, err) + require.NotNil(t, mc) assert.Equal(t, mc.RetryConfig.Attempts, uint(RPC_DEFAULT_RETRY_ATTEMPTS)) assert.Equal(t, mc.RetryConfig.Delay, RPC_DEFAULT_RETRY_DELAY) + _, err = NewMultiClient(lggr, []RPC{}) + require.Error(t, err) + // Expect second client to be set as backup. mc, err = NewMultiClient(lggr, []RPC{ {WSURL: s.URL}, diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 30ada2455ca..52276f027bc 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -4518,7 +4518,7 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] -GasLimit = 5400000 +GasLimit = 6000000 [Workflow] GasLimitDefault = 400000 @@ -4625,7 +4625,7 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] -GasLimit = 5400000 +GasLimit = 6000000 [Workflow] GasLimitDefault = 400000 diff --git a/flake.lock b/flake.lock index 71af2318c95..55ba1ddd565 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -26,11 +26,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1725354688, - "narHash": "sha256-KHHFemVt6C/hbGoMzIq7cpxmjdp+KZVZaqbvx02aliY=", + "lastModified": 1730625090, + "narHash": "sha256-lWfkkj+GEUM0UqYLD2Rx3zzILTL3xdmGJKGR4fwONpA=", "owner": "shazow", "repo": "foundry.nix", - "rev": "671672bd60a0d2e5f6757638fdf27e806df755a4", + "rev": "1c6a742bcbfd55a80de0e1f967a60174716a1560", "type": "github" }, "original": { @@ -45,11 +45,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1726594821, - "narHash": "sha256-ORImH+i+zOCMOdztNDqGDbyyFRC/FKmgbX8w50TNbQY=", + "lastModified": 1732296943, + "narHash": "sha256-I1RVZIODsNWyidRW4E7Mhwjj0iDHL1wEE90VyxmXBKc=", "owner": "goreleaser", "repo": "nur", - "rev": "bd2ee272ddfffbda9377a472131728e83ce2332d", + "rev": "d65134bd2cc0e930e6c03694734deb41ec72e030", "type": "github" }, "original": { @@ -90,11 +90,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1725103162, - "narHash": "sha256-Ym04C5+qovuQDYL/rKWSR+WESseQBbNAe5DsXNx5trY=", + "lastModified": 1732521221, + "narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=", "owner": "nixos", "repo": "nixpkgs", - "rev": "12228ff1752d7b7624a54e9c1af4b222b3c1073b", + "rev": "4633a7c72337ea8fd23a4f2ba3972865e3ec685d", "type": "github" }, "original": { @@ -106,11 +106,11 @@ }, "nur": { "locked": { - "lastModified": 1727912806, - "narHash": "sha256-LDOTTOGPaEP233gBrL8dnPGopc1lqcJFe0VB/+K/yWc=", + "lastModified": 1732854630, + "narHash": "sha256-ZliP697Djpq+JM4MuO6kvj5RWjCdg39ZQ2moFoqFbdE=", "owner": "nix-community", "repo": "NUR", - "rev": "9d9bcd30fec126b08b49020b7af08bc1aad66210", + "rev": "cc2a3158b6a714b98a8b891d6dcfc3a43039051f", "type": "github" }, "original": { diff --git a/go.mod b/go.mod index 314b6f32aa1..35069d38bbf 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,12 @@ module github.com/smartcontractkit/chainlink/v2 -go 1.23 +go 1.23.3 + +toolchain go1.23.4 require ( github.com/Depado/ginprom v1.8.0 - github.com/Masterminds/semver/v3 v3.2.1 + github.com/Masterminds/semver/v3 v3.3.0 github.com/Masterminds/sprig/v3 v3.2.3 github.com/NethermindEth/juno v0.3.1 github.com/NethermindEth/starknet.go v0.7.1-0.20240401080518-34a506f3cfdb @@ -31,7 +33,7 @@ require ( github.com/go-ldap/ldap/v3 v3.4.6 github.com/go-viper/mapstructure/v2 v2.1.0 github.com/go-webauthn/webauthn v0.9.4 - github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da + github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 github.com/google/uuid v1.6.0 github.com/gorilla/securecookie v1.1.2 github.com/gorilla/sessions v1.2.2 @@ -52,21 +54,21 @@ require ( github.com/jonboulle/clockwork v0.4.0 github.com/jpillora/backoff v1.0.0 github.com/kylelemons/godebug v1.1.0 - github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a + github.com/leanovate/gopter v0.2.11 github.com/lib/pq v1.10.9 github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/onsi/gomega v1.33.1 + github.com/onsi/gomega v1.34.2 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pelletier/go-toml v1.9.5 - github.com/pelletier/go-toml/v2 v2.2.2 + github.com/pelletier/go-toml/v2 v2.2.3 github.com/pkg/errors v0.9.1 github.com/pressly/goose/v3 v3.21.1 - github.com/prometheus/client_golang v1.20.0 + github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_model v0.6.1 - github.com/prometheus/common v0.59.1 + github.com/prometheus/common v0.60.0 github.com/prometheus/prometheus v0.54.1 github.com/robfig/cron/v3 v3.0.1 github.com/rogpeppe/go-internal v1.13.1 @@ -74,20 +76,20 @@ require ( github.com/scylladb/go-reflectx v1.0.1 github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 - github.com/smartcontractkit/chain-selectors v1.0.31 + github.com/smartcontractkit/chain-selectors v1.0.34 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db github.com/smartcontractkit/chainlink-feeds v0.1.1 - github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969 - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de - github.com/smartcontractkit/wsrpc v0.8.2 + github.com/smartcontractkit/wsrpc v0.8.3 github.com/spf13/cast v1.6.0 github.com/stretchr/testify v1.9.0 github.com/test-go/testify v1.1.4 @@ -104,6 +106,7 @@ require ( go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 go.opentelemetry.io/otel v1.31.0 go.opentelemetry.io/otel/metric v1.31.0 + go.opentelemetry.io/otel/sdk/metric v1.31.0 go.opentelemetry.io/otel/trace v1.31.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 @@ -295,6 +298,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runc v1.1.10 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect @@ -361,12 +365,10 @@ require ( go.opentelemetry.io/otel/log v0.6.0 // indirect go.opentelemetry.io/otel/sdk v1.31.0 // indirect go.opentelemetry.io/otel/sdk/log v0.6.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect - go.uber.org/ratelimit v0.3.0 // indirect + go.uber.org/ratelimit v0.3.1 // indirect golang.org/x/arch v0.11.0 // indirect golang.org/x/net v0.30.0 // indirect - golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/api v0.202.0 // indirect diff --git a/go.sum b/go.sum index a10dda308cb..caa877d66fa 100644 --- a/go.sum +++ b/go.sum @@ -11,7 +11,16 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ= @@ -21,6 +30,9 @@ cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLM cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v1.28.1 h1:XwPcZjgMCnU2tkwY10VleUjSAfpTj9RDn+kGrbYsi8o= cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= @@ -34,9 +46,12 @@ cloud.google.com/go/monitoring v1.21.1/go.mod h1:Rj++LKrlht9uBi8+Eb530dIrzG/cU/l cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.45.0 h1:5av0QcIVj77t+44mV4gffFC/LscFRUhto6UBMB5SimM= cloud.google.com/go/storage v1.45.0/go.mod h1:wpPblkIuMP5jCB/E48Pz9zIo2S/zD8g+ITmxKkPCITE= contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= @@ -97,8 +112,8 @@ github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJ github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -165,15 +180,16 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/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= @@ -214,6 +230,7 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI= github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= @@ -257,6 +274,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= @@ -342,7 +360,9 @@ github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.13.1 h1:vPfJZCkob6yTMEgS+0TwfTUfbHjfy/6vOJ8hUWX/uXE= github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -495,7 +515,10 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -503,6 +526,7 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -530,9 +554,12 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= @@ -546,6 +573,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -553,9 +582,15 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da h1:xRmpO92tb8y+Z85iUOMOicpCfaYcv7o3Cg3wKrIpg8g= -github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= @@ -572,6 +607,7 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= @@ -769,6 +805,7 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E 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= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -788,6 +825,7 @@ github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZY github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -801,8 +839,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= -github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= @@ -821,6 +859,7 @@ github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/z github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 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= @@ -909,6 +948,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= @@ -927,14 +968,14 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= -github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo= +github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= +github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -952,11 +993,12 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= @@ -967,6 +1009,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -982,8 +1025,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI= -github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -994,8 +1037,8 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1066,32 +1109,36 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm3KUgyMDyK0v0aOtUk4= -github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= +github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc h1:2xPgOrBA7Zjjulcn31Bp6q0kOrONbEnII7iE/vSQVHk= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d h1:0tnjo1gpG16PHAouXamgDAAu6e7PWaM0Ppq6dMWnjx0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57 h1:1BMTG66HnCIz+KMBWGvyzELNM6VHGwv2WKFhN7H49Sg= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57/go.mod h1:QPiorgpbLv4+Jn4YO6xxU4ftTu4T3QN8HwX3ImP59DE= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db/go.mod h1:yjb9d4q7+m8aGbjfTbkNoNuA4PeSxcUszsSZHDrvS0E= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969 h1:M/SMFCY4URO0H1eB9r3pkRv0LS3Ofxk/GapSgGrLfFI= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969/go.mod h1:mGmRvlk54ufCufV4EBWizOGtXoXfePoFAuYEVC8EwdY= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtOAzKS4PrPIiJX65BGo1aYiYZxFVEW+jc= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 h1:lvn9Yxah+QD1/PcgijLO0dNRa28HuQWZl8Kkxh46KJc= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= @@ -1100,10 +1147,12 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= -github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= +github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= @@ -1111,6 +1160,7 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1119,15 +1169,18 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= @@ -1230,6 +1283,7 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsr github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -1253,6 +1307,9 @@ go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYr go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= @@ -1263,6 +1320,7 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/detectors/gcp v1.31.0 h1:G1JQOreVrfhRkner+l4mrGxmfqYCAuy76asTDAo0xsA= @@ -1330,14 +1388,15 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= -go.uber.org/ratelimit v0.3.0 h1:IdZd9wqvFXnvLvSEBo0KPcGfkoBGNkpTHlrE3Rcjkjw= -go.uber.org/ratelimit v0.3.0/go.mod h1:So5LG7CV1zWpY1sHe+DXTJqQvOx+FFPFaAs2SnoyBaI= +go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= +go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -1393,6 +1452,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1401,9 +1461,12 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1422,6 +1485,7 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1430,11 +1494,21 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -1446,6 +1520,7 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= @@ -1454,6 +1529,13 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1463,7 +1545,9 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1506,17 +1590,29 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1548,6 +1644,7 @@ golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= @@ -1563,6 +1660,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= @@ -1610,14 +1708,31 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1641,8 +1756,19 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.202.0 h1:y1iuVHMqokQbimW79ZqPZWo4CiyFu6HcCYHwSNyzlfo= google.golang.org/api v0.202.0/go.mod h1:3Jjeq7M/SFblTNCp7ES2xhq+WvGL0KeXI0joHQBfwTQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -1651,6 +1777,8 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1670,12 +1798,33 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4= google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= @@ -1694,9 +1843,16 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/stats/opentelemetry v0.0.0-20241022174616-4bb0170ac65f h1:TsfHqsKI7qhOoYugDRyFDSKAuzegDVmkSCpjUyLkb+8= @@ -1709,6 +1865,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -1732,6 +1889,7 @@ gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= @@ -1762,6 +1920,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= diff --git a/integration-tests/.tool-versions b/integration-tests/.tool-versions index 5d980451979..3e44e439ff2 100644 --- a/integration-tests/.tool-versions +++ b/integration-tests/.tool-versions @@ -2,5 +2,5 @@ golang 1.23.3 k3d 5.4.6 kubectl 1.25.5 nodejs 20.13.1 -golangci-lint 1.61.1 +golangci-lint 1.62.0 task 3.35.1 diff --git a/integration-tests/actions/ocr2_helpers.go b/integration-tests/actions/ocr2_helpers.go index 1d386b158a0..842395bb25b 100644 --- a/integration-tests/actions/ocr2_helpers.go +++ b/integration-tests/actions/ocr2_helpers.go @@ -4,12 +4,15 @@ import ( "crypto/ed25519" "encoding/hex" "fmt" + "net/http" "strings" "time" + "github.com/avast/retry-go" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/lib/pq" + "github.com/rs/zerolog" "github.com/rs/zerolog/log" "golang.org/x/sync/errgroup" "gopkg.in/guregu/null.v4" @@ -192,6 +195,7 @@ func CreateOCRv2Jobs( mockServerValue int, // Value to get from the mock server when querying the path chainId int64, // EVM chain ID forwardingAllowed bool, + l zerolog.Logger, ) error { // Collect P2P ID bootstrapP2PIds, err := bootstrapNode.MustReadP2PKeys() @@ -218,6 +222,9 @@ func CreateOCRv2Jobs( } } + // Initialize map to store job IDs for each chainlink node + jobIDs := make(map[*nodeclient.ChainlinkK8sClient][]string) + for _, ocrInstance := range ocrInstances { bootstrapSpec := &nodeclient.OCR2TaskJobSpec{ Name: fmt.Sprintf("ocr2-bootstrap-%s", ocrInstance.Address()), @@ -284,10 +291,46 @@ func CreateOCRv2Jobs( P2PV2Bootstrappers: pq.StringArray{p2pV2Bootstrapper}, // bootstrap node key and address @bootstrap:6690 }, } - _, err = chainlinkNode.MustCreateJob(ocrSpec) + var ocrJob *nodeclient.Job + ocrJob, err = chainlinkNode.MustCreateJob(ocrSpec) if err != nil { return fmt.Errorf("creating OCR task job on OCR node have failed: %w", err) } + jobIDs[chainlinkNode] = append(jobIDs[chainlinkNode], ocrJob.Data.ID) // Store each job ID per node + } + } + l.Info().Msg("Verify OCRv2 jobs have been created") + for chainlinkNode, ids := range jobIDs { + for _, jobID := range ids { + err := retry.Do( + func() error { + _, resp, err := chainlinkNode.ReadJob(jobID) + if err != nil { + return err + } + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("unexpected response status: %d", resp.StatusCode) + } + l.Info(). + Str("Node", chainlinkNode.PodName). + Str("Job ID", jobID). + Msg("OCRv2 job successfully created") + return nil + }, + retry.Attempts(4), + retry.Delay(time.Second*2), + retry.OnRetry(func(n uint, err error) { + l.Debug(). + Str("Node", chainlinkNode.PodName). + Str("Job ID", jobID). + Uint("Attempt", n+1). + Err(err). + Msg("Retrying job verification") + }), + ) + if err != nil { + l.Error().Err(err).Str("Node", chainlinkNode.PodName).Str("JobID", jobID).Msg("Failed to verify OCRv2 job creation") + } } } return nil diff --git a/integration-tests/benchmark/automation_test.go b/integration-tests/benchmark/automation_test.go index 0a63ff2c27a..c4a113a8d99 100644 --- a/integration-tests/benchmark/automation_test.go +++ b/integration-tests/benchmark/automation_test.go @@ -77,7 +77,7 @@ func TestAutomationBenchmark(t *testing.T) { config, err := tc.GetConfig([]string{testType}, tc.Automation) require.NoError(t, err, "Error getting test config") - testEnvironment, benchmarkNetwork := SetupAutomationBenchmarkEnv(t, &config) + testEnvironment, benchmarkNetwork := SetupAutomationBenchmarkEnv(t, testType, &config) if testEnvironment.WillUseRemoteRunner() { return } @@ -245,7 +245,7 @@ var networkConfig = map[string]NetworkConfig{ }, } -func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.AutomationBenchmarkTestConfig) (*environment.Environment, blockchain.EVMNetwork) { +func SetupAutomationBenchmarkEnv(t *testing.T, testType string, keeperTestConfig types.AutomationBenchmarkTestConfig) (*environment.Environment, blockchain.EVMNetwork) { l := logging.GetTestLogger(t) testNetwork := networks.MustGetSelectedNetworkConfig(keeperTestConfig.GetNetworkConfig())[0] // Environment currently being used to run benchmark test on blockTime := "1" @@ -259,6 +259,12 @@ func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.Automation networkName = strings.ReplaceAll(networkName, "_", "-") testNetwork.Name = networkName + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(string(tc.Keeper), testType) + require.NoError(t, err, "Error creating required chain.link labels for namespace") + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(string(tc.Keeper), testType) + require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") + testEnvironment := environment.New(&environment.Config{ TTL: time.Hour * 720, // 30 days, NamespacePrefix: fmt.Sprintf( @@ -269,6 +275,9 @@ func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.Automation ), Test: t, PreventPodEviction: true, + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, }) dbResources := dbResources @@ -316,7 +325,6 @@ func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.Automation }, })) } - var err error if testNetwork.Simulated { // TODO we need to update the image in CTF, the old one is not available anymore // deploy blockscout if running on simulated diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index d0587dad789..492ee2fd0fa 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -4379,21 +4379,30 @@ func NewBalanceSheet() *BalanceSheet { } } +type attestationStatusResponse struct { + Status string `json:"status"` + Attestation string `json:"attestation"` + Error string `json:"error"` +} + // SetMockServerWithUSDCAttestation responds with a mock attestation for any msgHash // The path is set with regex to match any path that starts with /v1/attestations func SetMockServerWithUSDCAttestation( killGrave *ctftestenv.Killgrave, mockserver *ctfClient.MockserverClient, + isFaulty bool, ) error { path := "/v1/attestations" - response := struct { - Status string `json:"status"` - Attestation string `json:"attestation"` - Error string `json:"error"` - }{ + response := attestationStatusResponse{ Status: "complete", Attestation: "0x9049623e91719ef2aa63c55f357be2529b0e7122ae552c18aff8db58b4633c4d3920ff03d3a6d1ddf11f06bf64d7fd60d45447ac81f527ba628877dc5ca759651b08ffae25a6d3b1411749765244f0a1c131cbfe04430d687a2e12fd9d2e6dc08e118ad95d94ad832332cf3c4f7a4f3da0baa803b7be024b02db81951c0f0714de1b", } + if isFaulty { + response = attestationStatusResponse{ + Status: "pending", + Error: "internal error", + } + } if killGrave == nil && mockserver == nil { return fmt.Errorf("both killgrave and mockserver are nil") } diff --git a/integration-tests/ccip-tests/load/ccip_loadgen.go b/integration-tests/ccip-tests/load/ccip_loadgen.go index 3ce770d31bc..d562cce88b2 100644 --- a/integration-tests/ccip-tests/load/ccip_loadgen.go +++ b/integration-tests/ccip-tests/load/ccip_loadgen.go @@ -300,7 +300,7 @@ func (c *CCIPE2ELoad) Call(_ *wasp.Generator) *wasp.Response { } // the msg is no longer needed, so we can clear it to avoid holding extra data during load - // nolint:ineffassign,staticcheck + //nolint:ineffassign,staticcheck msg = router.ClientEVM2AnyMessage{} txConfirmationTime := time.Now().UTC() diff --git a/integration-tests/ccip-tests/testsetups/ccip.go b/integration-tests/ccip-tests/testsetups/ccip.go index 52901c4161a..fbfbc4c1ccd 100644 --- a/integration-tests/ccip-tests/testsetups/ccip.go +++ b/integration-tests/ccip-tests/testsetups/ccip.go @@ -37,6 +37,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" integrationactions "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" @@ -1153,7 +1154,7 @@ func CCIPDefaultTestSetUp( // if it's a new USDC deployment, set up mock server for attestation, // we need to set it only once for all the lanes as the attestation path uses regex to match the path for // all messages across all lanes - err = actions.SetMockServerWithUSDCAttestation(killgrave, setUpArgs.Env.MockServer) + err = actions.SetMockServerWithUSDCAttestation(killgrave, setUpArgs.Env.MockServer, false) require.NoError(t, err, "failed to set up mock server for attestation") } } @@ -1414,9 +1415,19 @@ func (o *CCIPTestSetUpOutputs) CreateEnvironment( } func createEnvironmentConfig(t *testing.T, envName string, testConfig *CCIPTestConfig, reportPath string) *environment.Config { + testType := testConfig.TestGroupInput.Type + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(string(tc.CCIP), testType) + require.NoError(t, err, "Error creating required chain.link labels for namespace") + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(string(tc.CCIP), testType) + require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") + envConfig := &environment.Config{ NamespacePrefix: envName, Test: t, + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, // PreventPodEviction: true, //TODO: enable this once we have a way to handle pod eviction } if pointer.GetBool(testConfig.TestGroupInput.StoreLaneConfig) { diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index 73ae7c07378..80e4a46581e 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -197,11 +197,20 @@ func TestAutomationChaos(t *testing.T) { t.Parallel() network := networks.MustGetSelectedNetworkConfig(config.Network)[0] // Need a new copy of the network for each test + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(string(tc.Automation), "chaos") + require.NoError(t, err, "Error creating required chain.link labels for namespace") + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(string(tc.Automation), "chaos") + require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") + testEnvironment := environment. New(&environment.Config{ NamespacePrefix: fmt.Sprintf("chaos-automation-%s", name), TTL: time.Hour * 1, Test: t, + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, }). AddHelm(testCase.networkChart). AddHelm(testCase.clChart) diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go index 41017d7eeb7..f072adcc46a 100644 --- a/integration-tests/chaos/ocr_chaos_test.go +++ b/integration-tests/chaos/ocr_chaos_test.go @@ -141,15 +141,24 @@ func TestOCRChaos(t *testing.T) { t.Run(fmt.Sprintf("OCR_%s", name), func(t *testing.T) { t.Parallel() + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels("data-feedsv1.0", "chaos") + require.NoError(t, err, "Error creating required chain.link labels for namespace") + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels("data-feedsv1.0", "chaos") + require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") + testEnvironment := environment.New(&environment.Config{ NamespacePrefix: fmt.Sprintf("chaos-ocr-%s", name), Test: t, + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, }). AddHelm(mockservercfg.New(nil)). AddHelm(mockserver.New(nil)). AddHelm(testCase.networkChart). AddHelm(testCase.clChart) - err := testEnvironment.Run() + err = testEnvironment.Run() require.NoError(t, err) if testEnvironment.WillUseRemoteRunner() { return diff --git a/integration-tests/contracts/ccipreader_test.go b/integration-tests/contracts/ccipreader_test.go new file mode 100644 index 00000000000..3028f4707a4 --- /dev/null +++ b/integration-tests/contracts/ccipreader_test.go @@ -0,0 +1,1479 @@ +package contracts + +import ( + "context" + "fmt" + "math/big" + "sort" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient/simulated" + "github.com/jmoiron/sqlx" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" + + "github.com/smartcontractkit/chainlink-ccip/plugintypes" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/integration-tests/utils/pgtest" + + readermocks "github.com/smartcontractkit/chainlink-ccip/mocks/pkg/contractreader" + + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_reader_tester" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + "github.com/smartcontractkit/chainlink-ccip/pkg/contractreader" + ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" + + evmchaintypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" +) + +const ( + chainS1 = cciptypes.ChainSelector(1) + chainS2 = cciptypes.ChainSelector(2) + chainS3 = cciptypes.ChainSelector(3) + chainD = cciptypes.ChainSelector(4) +) + +var ( + defaultGasPrice = assets.GWei(10) +) + +var ( + onrampABI = evmchaintypes.MustGetABI(onramp.OnRampABI) + offrampABI = evmchaintypes.MustGetABI(offramp.OffRampABI) +) + +func setupGetCommitGTETimestampTest(ctx context.Context, t testing.TB, finalityDepth int64, useHeavyDB bool) (*testSetupData, int64, common.Address) { + sb, auth := setupSimulatedBackendAndAuth(t) + onRampAddress := utils.RandomAddress() + s := testSetup(ctx, t, testSetupParams{ + ReaderChain: chainD, + DestChain: chainD, + OnChainSeqNums: nil, + Cfg: evmconfig.DestReaderConfig, + ToMockBindings: map[cciptypes.ChainSelector][]types.BoundContract{ + chainS1: { + { + Address: onRampAddress.Hex(), + Name: consts.ContractNameOnRamp, + }, + }, + }, + BindTester: true, + ContractNameToBind: consts.ContractNameOffRamp, + SimulatedBackend: sb, + Auth: auth, + FinalityDepth: finalityDepth, + UseHeavyDB: useHeavyDB, + }) + + return s, finalityDepth, onRampAddress +} + +func setupExecutedMessageRangesTest(ctx context.Context, t testing.TB, useHeavyDB bool) *testSetupData { + sb, auth := setupSimulatedBackendAndAuth(t) + return testSetup(ctx, t, testSetupParams{ + ReaderChain: chainD, + DestChain: chainD, + OnChainSeqNums: nil, + Cfg: evmconfig.DestReaderConfig, + // Cfg: cfg, + ToBindContracts: nil, + ToMockBindings: nil, + BindTester: true, + ContractNameToBind: consts.ContractNameOffRamp, + SimulatedBackend: sb, + Auth: auth, + UseHeavyDB: useHeavyDB, + }) +} + +func setupMsgsBetweenSeqNumsTest(ctx context.Context, t testing.TB, useHeavyDB bool) *testSetupData { + sb, auth := setupSimulatedBackendAndAuth(t) + return testSetup(ctx, t, testSetupParams{ + ReaderChain: chainS1, + DestChain: chainD, + OnChainSeqNums: nil, + Cfg: evmconfig.SourceReaderConfig, + ToBindContracts: nil, + ToMockBindings: nil, + BindTester: true, + ContractNameToBind: consts.ContractNameOnRamp, + SimulatedBackend: sb, + Auth: auth, + UseHeavyDB: useHeavyDB, + }) +} + +func emitCommitReports(ctx context.Context, t *testing.T, s *testSetupData, numReports int, tokenA common.Address, onRampAddress common.Address) uint64 { + var firstReportTs uint64 + for i := uint8(0); int(i) < numReports; i++ { + _, err := s.contract.EmitCommitReportAccepted(s.auth, ccip_reader_tester.OffRampCommitReport{ + PriceUpdates: ccip_reader_tester.InternalPriceUpdates{ + TokenPriceUpdates: []ccip_reader_tester.InternalTokenPriceUpdate{ + { + SourceToken: tokenA, + UsdPerToken: big.NewInt(1000), + }, + }, + GasPriceUpdates: []ccip_reader_tester.InternalGasPriceUpdate{ + { + DestChainSelector: uint64(chainD), + UsdPerUnitGas: big.NewInt(90), + }, + }, + }, + MerkleRoots: []ccip_reader_tester.InternalMerkleRoot{ + { + SourceChainSelector: uint64(chainS1), + MinSeqNr: 10, + MaxSeqNr: 20, + MerkleRoot: [32]byte{i + 1}, + OnRampAddress: common.LeftPadBytes(onRampAddress.Bytes(), 32), + }, + }, + RmnSignatures: []ccip_reader_tester.IRMNRemoteSignature{ + { + R: [32]byte{1}, + S: [32]byte{2}, + }, + { + R: [32]byte{3}, + S: [32]byte{4}, + }, + }, + }) + require.NoError(t, err) + bh := s.sb.Commit() + b, err := s.sb.Client().BlockByHash(ctx, bh) + require.NoError(t, err) + if firstReportTs == 0 { + firstReportTs = b.Time() + } + } + return firstReportTs +} + +func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + s, _, onRampAddress := setupGetCommitGTETimestampTest(ctx, t, 0, false) + + tokenA := common.HexToAddress("123") + const numReports = 5 + + firstReportTs := emitCommitReports(ctx, t, s, numReports, tokenA, onRampAddress) + + // Need to replay as sometimes the logs are not picked up by the log poller (?) + // Maybe another situation where chain reader doesn't register filters as expected. + require.NoError(t, s.lp.Replay(ctx, 1)) + + var reports []plugintypes.CommitPluginReportWithMeta + var err error + require.Eventually(t, func() bool { + reports, err = s.reader.CommitReportsGTETimestamp( + ctx, + chainD, + // Skips first report + //nolint:gosec // this won't overflow + time.Unix(int64(firstReportTs)+1, 0), + 10, + ) + require.NoError(t, err) + return len(reports) == numReports-1 + }, 30*time.Second, 50*time.Millisecond) + + assert.Len(t, reports, numReports-1) + assert.Len(t, reports[0].Report.MerkleRoots, 1) + assert.Equal(t, chainS1, reports[0].Report.MerkleRoots[0].ChainSel) + assert.Equal(t, onRampAddress.Bytes(), []byte(reports[0].Report.MerkleRoots[0].OnRampAddress)) + assert.Equal(t, cciptypes.SeqNum(10), reports[0].Report.MerkleRoots[0].SeqNumsRange.Start()) + assert.Equal(t, cciptypes.SeqNum(20), reports[0].Report.MerkleRoots[0].SeqNumsRange.End()) + assert.Equal(t, "0x0200000000000000000000000000000000000000000000000000000000000000", + reports[0].Report.MerkleRoots[0].MerkleRoot.String()) + assert.Equal(t, tokenA.String(), string(reports[0].Report.PriceUpdates.TokenPriceUpdates[0].TokenID)) + assert.Equal(t, uint64(1000), reports[0].Report.PriceUpdates.TokenPriceUpdates[0].Price.Uint64()) + assert.Equal(t, chainD, reports[0].Report.PriceUpdates.GasPriceUpdates[0].ChainSel) + assert.Equal(t, uint64(90), reports[0].Report.PriceUpdates.GasPriceUpdates[0].GasPrice.Uint64()) +} + +func TestCCIPReader_CommitReportsGTETimestamp_RespectsFinality(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + var finalityDepth int64 = 10 + s, _, onRampAddress := setupGetCommitGTETimestampTest(ctx, t, finalityDepth, false) + + tokenA := common.HexToAddress("123") + const numReports = 5 + + firstReportTs := emitCommitReports(ctx, t, s, numReports, tokenA, onRampAddress) + + // Need to replay as sometimes the logs are not picked up by the log poller (?) + // Maybe another situation where chain reader doesn't register filters as expected. + require.NoError(t, s.lp.Replay(ctx, 1)) + + var reports []plugintypes.CommitPluginReportWithMeta + var err error + // Will not return any reports as the finality depth is not reached. + require.Never(t, func() bool { + reports, err = s.reader.CommitReportsGTETimestamp( + ctx, + chainD, + // Skips first report + //nolint:gosec // this won't overflow + time.Unix(int64(firstReportTs)+1, 0), + 10, + ) + require.NoError(t, err) + return len(reports) == numReports-1 + }, 20*time.Second, 50*time.Millisecond) + + // Commit finality depth number of blocks. + for i := 0; i < int(finalityDepth); i++ { + s.sb.Commit() + } + + require.Eventually(t, func() bool { + reports, err = s.reader.CommitReportsGTETimestamp( + ctx, + chainD, + // Skips first report + //nolint:gosec // this won't overflow + time.Unix(int64(firstReportTs)+1, 0), + 10, + ) + require.NoError(t, err) + return len(reports) == numReports-1 + }, 30*time.Second, 50*time.Millisecond) + + assert.Len(t, reports, numReports-1) + assert.Len(t, reports[0].Report.MerkleRoots, 1) + assert.Equal(t, chainS1, reports[0].Report.MerkleRoots[0].ChainSel) + assert.Equal(t, onRampAddress.Bytes(), []byte(reports[0].Report.MerkleRoots[0].OnRampAddress)) + assert.Equal(t, cciptypes.SeqNum(10), reports[0].Report.MerkleRoots[0].SeqNumsRange.Start()) + assert.Equal(t, cciptypes.SeqNum(20), reports[0].Report.MerkleRoots[0].SeqNumsRange.End()) + assert.Equal(t, "0x0200000000000000000000000000000000000000000000000000000000000000", + reports[0].Report.MerkleRoots[0].MerkleRoot.String()) + assert.Equal(t, tokenA.String(), string(reports[0].Report.PriceUpdates.TokenPriceUpdates[0].TokenID)) + assert.Equal(t, uint64(1000), reports[0].Report.PriceUpdates.TokenPriceUpdates[0].Price.Uint64()) + assert.Equal(t, chainD, reports[0].Report.PriceUpdates.GasPriceUpdates[0].ChainSel) + assert.Equal(t, uint64(90), reports[0].Report.PriceUpdates.GasPriceUpdates[0].GasPrice.Uint64()) +} + +func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + s := setupExecutedMessageRangesTest(ctx, t, false) + _, err := s.contract.EmitExecutionStateChanged( + s.auth, + uint64(chainS1), + 14, + cciptypes.Bytes32{1, 0, 0, 1}, + cciptypes.Bytes32{1, 0, 0, 1, 1, 0, 0, 1}, + 1, + []byte{1, 2, 3, 4}, + big.NewInt(250_000), + ) + require.NoError(t, err) + s.sb.Commit() + + _, err = s.contract.EmitExecutionStateChanged( + s.auth, + uint64(chainS1), + 15, + cciptypes.Bytes32{1, 0, 0, 2}, + cciptypes.Bytes32{1, 0, 0, 2, 1, 0, 0, 2}, + 1, + []byte{1, 2, 3, 4, 5}, + big.NewInt(350_000), + ) + require.NoError(t, err) + s.sb.Commit() + + // Need to replay as sometimes the logs are not picked up by the log poller (?) + // Maybe another situation where chain reader doesn't register filters as expected. + require.NoError(t, s.lp.Replay(ctx, 1)) + + var executedRanges []cciptypes.SeqNumRange + require.Eventually(t, func() bool { + executedRanges, err = s.reader.ExecutedMessageRanges( + ctx, + chainS1, + chainD, + cciptypes.NewSeqNumRange(14, 15), + ) + require.NoError(t, err) + return len(executedRanges) == 2 + }, tests.WaitTimeout(t), 50*time.Millisecond) + + assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].Start()) + assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].End()) + + assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].Start()) + assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].End()) +} + +func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + + s := setupMsgsBetweenSeqNumsTest(ctx, t, false) + _, err := s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ + Header: ccip_reader_tester.InternalRampMessageHeader{ + MessageId: [32]byte{1, 0, 0, 0, 0}, + SourceChainSelector: uint64(chainS1), + DestChainSelector: uint64(chainD), + SequenceNumber: 10, + }, + Sender: utils.RandomAddress(), + Data: make([]byte, 0), + Receiver: utils.RandomAddress().Bytes(), + ExtraArgs: make([]byte, 0), + FeeToken: utils.RandomAddress(), + FeeTokenAmount: big.NewInt(1), + FeeValueJuels: big.NewInt(2), + TokenAmounts: []ccip_reader_tester.InternalEVM2AnyTokenTransfer{{Amount: big.NewInt(1)}, {Amount: big.NewInt(2)}}, + }) + require.NoError(t, err) + + _, err = s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ + Header: ccip_reader_tester.InternalRampMessageHeader{ + MessageId: [32]byte{1, 0, 0, 0, 1}, + SourceChainSelector: uint64(chainS1), + DestChainSelector: uint64(chainD), + SequenceNumber: 15, + }, + Sender: utils.RandomAddress(), + Data: make([]byte, 0), + Receiver: utils.RandomAddress().Bytes(), + ExtraArgs: make([]byte, 0), + FeeToken: utils.RandomAddress(), + FeeTokenAmount: big.NewInt(3), + FeeValueJuels: big.NewInt(4), + TokenAmounts: []ccip_reader_tester.InternalEVM2AnyTokenTransfer{{Amount: big.NewInt(3)}, {Amount: big.NewInt(4)}}, + }) + require.NoError(t, err) + + s.sb.Commit() + + // Need to replay as sometimes the logs are not picked up by the log poller (?) + // Maybe another situation where chain reader doesn't register filters as expected. + require.NoError(t, s.lp.Replay(ctx, 1)) + + var msgs []cciptypes.Message + require.Eventually(t, func() bool { + msgs, err = s.reader.MsgsBetweenSeqNums( + ctx, + chainS1, + cciptypes.NewSeqNumRange(5, 20), + ) + require.NoError(t, err) + return len(msgs) == 2 + }, tests.WaitTimeout(t), 100*time.Millisecond) + + require.Len(t, msgs, 2) + // sort to ensure ascending order of sequence numbers. + sort.Slice(msgs, func(i, j int) bool { + return msgs[i].Header.SequenceNumber < msgs[j].Header.SequenceNumber + }) + require.Equal(t, cciptypes.SeqNum(10), msgs[0].Header.SequenceNumber) + require.Equal(t, big.NewInt(1), msgs[0].FeeTokenAmount.Int) + require.Equal(t, big.NewInt(2), msgs[0].FeeValueJuels.Int) + require.Equal(t, int64(1), msgs[0].TokenAmounts[0].Amount.Int64()) + require.Equal(t, int64(2), msgs[0].TokenAmounts[1].Amount.Int64()) + + require.Equal(t, cciptypes.SeqNum(15), msgs[1].Header.SequenceNumber) + require.Equal(t, big.NewInt(3), msgs[1].FeeTokenAmount.Int) + require.Equal(t, big.NewInt(4), msgs[1].FeeValueJuels.Int) + require.Equal(t, int64(3), msgs[1].TokenAmounts[0].Amount.Int64()) + require.Equal(t, int64(4), msgs[1].TokenAmounts[1].Amount.Int64()) + + for _, msg := range msgs { + require.Equal(t, chainS1, msg.Header.SourceChainSelector) + require.Equal(t, chainD, msg.Header.DestChainSelector) + } +} + +func TestCCIPReader_NextSeqNum(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + + onChainSeqNums := map[cciptypes.ChainSelector]cciptypes.SeqNum{ + chainS1: 10, + chainS2: 20, + chainS3: 30, + } + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOffRamp: { + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.MethodNameGetSourceChainConfig: { + ChainSpecificName: "getSourceChainConfig", + ReadType: evmtypes.Method, + }, + }, + }, + }, + } + + sb, auth := setupSimulatedBackendAndAuth(t) + s := testSetup(ctx, t, testSetupParams{ + ReaderChain: chainD, + DestChain: chainD, + OnChainSeqNums: onChainSeqNums, + Cfg: cfg, + ToBindContracts: nil, + ToMockBindings: nil, + BindTester: true, + ContractNameToBind: consts.ContractNameOffRamp, + SimulatedBackend: sb, + Auth: auth, + }) + + seqNums, err := s.reader.NextSeqNum(ctx, []cciptypes.ChainSelector{chainS1, chainS2, chainS3}) + require.NoError(t, err) + assert.Len(t, seqNums, 3) + assert.Equal(t, cciptypes.SeqNum(10), seqNums[0]) + assert.Equal(t, cciptypes.SeqNum(20), seqNums[1]) + assert.Equal(t, cciptypes.SeqNum(30), seqNums[2]) +} + +func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + //env := NewMemoryEnvironmentContractsOnly(t, logger.TestLogger(t), 2, 4, nil) + env := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + }, nil) + state, err := changeset.LoadOnchainState(env.Env) + require.NoError(t, err) + + selectors := env.Env.AllChainSelectors() + destChain, srcChain := selectors[0], selectors[1] + + require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, destChain, srcChain, false)) + require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, srcChain, destChain, false)) + + reader := testSetupRealContracts( + ctx, + t, + destChain, + map[cciptypes.ChainSelector][]types.BoundContract{ + cciptypes.ChainSelector(srcChain): { + { + Address: state.Chains[srcChain].OnRamp.Address().String(), + Name: consts.ContractNameOnRamp, + }, + }, + }, + nil, + env, + ) + + maxExpectedSeqNum := uint64(10) + var i uint64 + for i = 1; i < maxExpectedSeqNum; i++ { + msg := changeset.DefaultRouterMessage(state.Chains[destChain].Receiver.Address()) + msgSentEvent := changeset.TestSendRequest(t, env.Env, state, srcChain, destChain, false, msg) + require.Equal(t, uint64(i), msgSentEvent.SequenceNumber) + require.Equal(t, uint64(i), msgSentEvent.Message.Header.Nonce) // check outbound nonce incremented + seqNum, err2 := reader.GetExpectedNextSequenceNumber(ctx, cs(srcChain), cs(destChain)) + require.NoError(t, err2) + require.Equal(t, cciptypes.SeqNum(i+1), seqNum) + } +} + +func TestCCIPReader_Nonces(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + var nonces = map[cciptypes.ChainSelector]map[common.Address]uint64{ + chainS1: { + utils.RandomAddress(): 10, + utils.RandomAddress(): 20, + }, + chainS2: { + utils.RandomAddress(): 30, + utils.RandomAddress(): 40, + }, + chainS3: { + utils.RandomAddress(): 50, + utils.RandomAddress(): 60, + }, + } + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameNonceManager: { + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.MethodNameGetInboundNonce: { + ChainSpecificName: "getInboundNonce", + ReadType: evmtypes.Method, + }, + }, + }, + }, + } + + sb, auth := setupSimulatedBackendAndAuth(t) + s := testSetup(ctx, t, testSetupParams{ + ReaderChain: chainD, + DestChain: chainD, + Cfg: cfg, + BindTester: true, + ContractNameToBind: consts.ContractNameNonceManager, + SimulatedBackend: sb, + Auth: auth, + }) + + // Add some nonces. + for chain, addrs := range nonces { + for addr, nonce := range addrs { + _, err := s.contract.SetInboundNonce(s.auth, uint64(chain), nonce, common.LeftPadBytes(addr.Bytes(), 32)) + require.NoError(t, err) + } + } + s.sb.Commit() + + for sourceChain, addrs := range nonces { + var addrQuery []string + for addr := range addrs { + addrQuery = append(addrQuery, addr.String()) + } + addrQuery = append(addrQuery, utils.RandomAddress().String()) + + results, err := s.reader.Nonces(ctx, sourceChain, chainD, addrQuery) + require.NoError(t, err) + assert.Len(t, results, len(addrQuery)) + for addr, nonce := range addrs { + assert.Equal(t, nonce, results[addr.String()]) + } + } +} + +func Test_GetChainFeePriceUpdates(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + env := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + }, nil) + state, err := changeset.LoadOnchainState(env.Env) + require.NoError(t, err) + + selectors := env.Env.AllChainSelectors() + chain1, chain2 := selectors[0], selectors[1] + + require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain1, chain2, false)) + require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain2, chain1, false)) + + // Change the gas price for chain2 + feeQuoter := state.Chains[chain1].FeeQuoter + _, err = feeQuoter.UpdatePrices( + env.Env.Chains[chain1].DeployerKey, fee_quoter.InternalPriceUpdates{ + GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ + { + DestChainSelector: chain2, + UsdPerUnitGas: defaultGasPrice.ToInt(), + }, + }, + }, + ) + require.NoError(t, err) + be := env.Env.Chains[chain1].Client.(*memory.Backend) + be.Commit() + + gas, err := feeQuoter.GetDestinationChainGasPrice(&bind.CallOpts{}, chain2) + require.NoError(t, err) + require.Equal(t, defaultGasPrice.ToInt(), gas.Value) + + reader := testSetupRealContracts( + ctx, + t, + chain1, + //evmconfig.DestReaderConfig, + map[cciptypes.ChainSelector][]types.BoundContract{ + cciptypes.ChainSelector(chain1): { + { + Address: state.Chains[chain1].FeeQuoter.Address().String(), + Name: consts.ContractNameFeeQuoter, + }, + }, + }, + nil, + env, + ) + + updates := reader.GetChainFeePriceUpdate(ctx, []cciptypes.ChainSelector{cs(chain1), cs(chain2)}) + // only chain1 has a bound contract + require.Len(t, updates, 1) + require.Equal(t, defaultGasPrice.ToInt(), updates[cs(chain2)].Value.Int) +} + +func Test_LinkPriceUSD(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + env := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + }, nil) + state, err := changeset.LoadOnchainState(env.Env) + require.NoError(t, err) + + selectors := env.Env.AllChainSelectors() + chain1, chain2 := selectors[0], selectors[1] + + require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain1, chain2, false)) + require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain2, chain1, false)) + + reader := testSetupRealContracts( + ctx, + t, + chain1, + map[cciptypes.ChainSelector][]types.BoundContract{ + cciptypes.ChainSelector(chain1): { + { + Address: state.Chains[chain1].FeeQuoter.Address().String(), + Name: consts.ContractNameFeeQuoter, + }, + }, + }, + nil, + env, + ) + + linkPriceUSD, err := reader.LinkPriceUSD(ctx) + require.NoError(t, err) + require.NotNil(t, linkPriceUSD.Int) + require.Equal(t, changeset.DefaultInitialPrices.LinkPrice, linkPriceUSD.Int) +} + +func Test_GetMedianDataAvailabilityGasConfig(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + env := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 4, + Nodes: 4, + Bootstraps: 1, + }, nil) + state, err := changeset.LoadOnchainState(env.Env) + require.NoError(t, err) + + selectors := env.Env.AllChainSelectors() + destChain, chain1, chain2, chain3 := selectors[0], selectors[1], selectors[2], selectors[3] + + require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain1, destChain, false)) + require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain2, destChain, false)) + require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain3, destChain, false)) + + boundContracts := map[cciptypes.ChainSelector][]types.BoundContract{} + for i, selector := range env.Env.AllChainSelectorsExcluding([]uint64{destChain}) { + feeQuoter := state.Chains[selector].FeeQuoter + destChainCfg := changeset.DefaultFeeQuoterDestChainConfig() + //nolint:gosec // disable G115 + destChainCfg.DestDataAvailabilityOverheadGas = uint32(100 + i) + //nolint:gosec // disable G115 + destChainCfg.DestGasPerDataAvailabilityByte = uint16(200 + i) + //nolint:gosec // disable G115 + destChainCfg.DestDataAvailabilityMultiplierBps = uint16(1 + i) + _, err2 := feeQuoter.ApplyDestChainConfigUpdates(env.Env.Chains[selector].DeployerKey, []fee_quoter.FeeQuoterDestChainConfigArgs{ + { + DestChainSelector: destChain, + DestChainConfig: destChainCfg, + }, + }) + require.NoError(t, err2) + be := env.Env.Chains[selector].Client.(*memory.Backend) + be.Commit() + boundContracts[cs(selector)] = []types.BoundContract{ + { + Address: feeQuoter.Address().String(), + Name: consts.ContractNameFeeQuoter, + }, + } + } + + reader := testSetupRealContracts( + ctx, + t, + destChain, + boundContracts, + nil, + env, + ) + + daConfig, err := reader.GetMedianDataAvailabilityGasConfig(ctx) + require.NoError(t, err) + + // Verify the results + require.Equal(t, uint32(101), daConfig.DestDataAvailabilityOverheadGas) + require.Equal(t, uint16(201), daConfig.DestGasPerDataAvailabilityByte) + require.Equal(t, uint16(2), daConfig.DestDataAvailabilityMultiplierBps) +} + +func Test_GetWrappedNativeTokenPriceUSD(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + env := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + }, nil) + state, err := changeset.LoadOnchainState(env.Env) + require.NoError(t, err) + + selectors := env.Env.AllChainSelectors() + chain1, chain2 := selectors[0], selectors[1] + + require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain1, chain2, false)) + require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(env.Env, state, chain2, chain1, false)) + + reader := testSetupRealContracts( + ctx, + t, + chain1, + map[cciptypes.ChainSelector][]types.BoundContract{ + cciptypes.ChainSelector(chain1): { + { + Address: state.Chains[chain1].FeeQuoter.Address().String(), + Name: consts.ContractNameFeeQuoter, + }, + { + Address: state.Chains[chain1].Router.Address().String(), + Name: consts.ContractNameRouter, + }, + }, + }, + nil, + env, + ) + + prices := reader.GetWrappedNativeTokenPriceUSD(ctx, []cciptypes.ChainSelector{cciptypes.ChainSelector(chain1), cciptypes.ChainSelector(chain2)}) + + // Only chainD has reader contracts bound + require.Len(t, prices, 1) + require.Equal(t, changeset.DefaultInitialPrices.WethPrice, prices[cciptypes.ChainSelector(chain1)].Int) +} + +// Benchmark Results: +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_0_MatchLogs_0-14 16948 67728 ns/op 30387 B/op 417 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_1_MatchLogs_10-14 1650 741741 ns/op 528334 B/op 9929 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_10_MatchLogs_100-14 195 6096328 ns/op 4739856 B/op 92345 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_100_MatchLogs_10000-14 2 582712583 ns/op 454375304 B/op 8931990 allocs/op +func Benchmark_CCIPReader_CommitReportsGTETimestamp(b *testing.B) { + tests := []struct { + logsInsertedFirst int + logsInsertedMatching int + }{ + {0, 0}, + {1, 10}, + {10, 100}, + {100, 10_000}, + } + + for _, tt := range tests { + b.Run(fmt.Sprintf("FirstLogs_%d_MatchLogs_%d", tt.logsInsertedMatching, tt.logsInsertedFirst), func(b *testing.B) { + benchmarkCommitReports(b, tt.logsInsertedFirst, tt.logsInsertedMatching) + }) + } +} + +func benchmarkCommitReports(b *testing.B, logsInsertedFirst int, logsInsertedMatching int) { + // Initialize test setup + ctx := tests.Context(b) + s, _, _ := setupGetCommitGTETimestampTest(ctx, b, 0, true) + + if logsInsertedFirst > 0 { + populateDatabaseForCommitReportAccepted(ctx, b, s, chainD, chainS1, logsInsertedFirst, 0) + } + + queryTimestamp := time.Now() + + if logsInsertedMatching > 0 { + populateDatabaseForCommitReportAccepted(ctx, b, s, chainD, chainS1, logsInsertedMatching, logsInsertedFirst) + } + + // Reset timer to measure only the query time + b.ResetTimer() + + for i := 0; i < b.N; i++ { + reports, err := s.reader.CommitReportsGTETimestamp(ctx, chainD, queryTimestamp, logsInsertedFirst) + require.NoError(b, err) + require.Len(b, reports, logsInsertedFirst) + } +} + +func populateDatabaseForCommitReportAccepted( + ctx context.Context, + b *testing.B, + testEnv *testSetupData, + destChain cciptypes.ChainSelector, + sourceChain cciptypes.ChainSelector, + numOfReports int, + offset int, +) { + var logs []logpoller.Log + commitReportEvent, exists := offrampABI.Events[consts.EventNameCommitReportAccepted] + require.True(b, exists, "Event CommitReportAccepted not found in ABI") + + commitReportEventSig := commitReportEvent.ID + commitReportAddress := testEnv.contractAddr + + // Calculate timestamp based on whether these are the first logs or matching logs + var timestamp time.Time + if offset == 0 { + // For first set of logs, set timestamp to 1 hour ago + timestamp = time.Now().Add(-1 * time.Hour) + } else { + // For matching logs, use current time + timestamp = time.Now() + } + + for i := 0; i < numOfReports; i++ { + // Calculate unique BlockNumber and LogIndex + blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers + logIndex := int64(offset + i + 1) // Offset ensures unique log indices + + // Simulate merkleRoots + merkleRoots := []offramp.InternalMerkleRoot{ + { + SourceChainSelector: uint64(sourceChain), + OnRampAddress: utils.RandomAddress().Bytes(), + // #nosec G115 + MinSeqNr: uint64(i * 100), + // #nosec G115 + MaxSeqNr: uint64(i*100 + 99), + MerkleRoot: utils.RandomBytes32(), + }, + } + + sourceToken := utils.RandomAddress() + + // Simulate priceUpdates + priceUpdates := offramp.InternalPriceUpdates{ + TokenPriceUpdates: []offramp.InternalTokenPriceUpdate{ + {SourceToken: sourceToken, UsdPerToken: big.NewInt(8)}, + }, + GasPriceUpdates: []offramp.InternalGasPriceUpdate{ + {DestChainSelector: uint64(1), UsdPerUnitGas: big.NewInt(10)}, + }, + } + + // Combine encoded data + encodedData, err := commitReportEvent.Inputs.Pack(merkleRoots, priceUpdates) + require.NoError(b, err) + + // Topics (first one is the event signature) + topics := [][]byte{ + commitReportEventSig[:], + } + + // Create log entry + logs = append(logs, logpoller.Log{ + EvmChainId: ubig.New(new(big.Int).SetUint64(uint64(destChain))), + LogIndex: logIndex, + BlockHash: utils.NewHash(), + BlockNumber: blockNumber, + BlockTimestamp: timestamp, + EventSig: commitReportEventSig, + Topics: topics, + Address: commitReportAddress, + TxHash: utils.NewHash(), + Data: encodedData, + CreatedAt: time.Now(), + }) + } + + // Insert logs into the database + require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) + require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfReports), timestamp, int64(offset+numOfReports))) +} + +// Benchmark Results: +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 13599 93414 ns/op 43389 B/op 654 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_10_EndSeq_20-14 13471 88392 ns/op 43011 B/op 651 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 2799 473396 ns/op 303737 B/op 4535 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 438 2724414 ns/op 2477573 B/op 37468 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 40 29118796 ns/op 12607995 B/op 179396 allocs/op +func Benchmark_CCIPReader_ExecutedMessageRanges(b *testing.B) { + tests := []struct { + logsInserted int + startSeqNum cciptypes.SeqNum + endSeqNum cciptypes.SeqNum + }{ + {0, 0, 10}, // no logs + {10, 10, 20}, // out of bounds + {10, 0, 9}, // get all messages with 10 logs + {100, 0, 100}, // get all messages with 100 logs + {100_000, 100_000 - 256, 100_000}, // get the last 256 messages + } + + for _, tt := range tests { + b.Run(fmt.Sprintf("LogsInserted_%d_StartSeq_%d_EndSeq_%d", tt.logsInserted, tt.startSeqNum, tt.endSeqNum), func(b *testing.B) { + benchmarkExecutedMessageRanges(b, tt.logsInserted, tt.startSeqNum, tt.endSeqNum) + }) + } +} + +func benchmarkExecutedMessageRanges(b *testing.B, logsInsertedFirst int, startSeqNum, endSeqNum cciptypes.SeqNum) { + // Initialize test setup + ctx := tests.Context(b) + s := setupExecutedMessageRangesTest(ctx, b, true) + expectedRangeLen := calculateExpectedRangeLen(logsInsertedFirst, startSeqNum, endSeqNum) + + // Insert logs in two phases based on parameters + if logsInsertedFirst > 0 { + populateDatabaseForExecutionStateChanged(ctx, b, s, chainS1, chainD, logsInsertedFirst, 0) + } + + // Reset timer to measure only the query time + b.ResetTimer() + + for i := 0; i < b.N; i++ { + executedRanges, err := s.reader.ExecutedMessageRanges( + ctx, + chainS1, + chainD, + cciptypes.NewSeqNumRange(startSeqNum, endSeqNum), + ) + require.NoError(b, err) + require.Len(b, executedRanges, expectedRangeLen) + } +} + +func populateDatabaseForExecutionStateChanged( + ctx context.Context, + b *testing.B, + testEnv *testSetupData, + sourceChain cciptypes.ChainSelector, + destChain cciptypes.ChainSelector, + numOfEvents int, + offset int, +) { + var logs []logpoller.Log + executionStateEvent, exists := offrampABI.Events[consts.EventNameExecutionStateChanged] + require.True(b, exists, "Event ExecutionStateChanged not found in ABI") + + executionStateEventSig := executionStateEvent.ID + executionStateEventAddress := testEnv.contractAddr + + for i := 0; i < numOfEvents; i++ { + // Calculate unique BlockNumber and LogIndex + blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers + logIndex := int64(offset + i + 1) // Offset ensures unique log indices + + // Populate fields for the event + sourceChainSelector := uint64(sourceChain) + // #nosec G115 + sequenceNumber := uint64(offset + i) + messageID := utils.NewHash() + messageHash := utils.NewHash() + state := uint8(1) + returnData := []byte{0x01, 0x02} + gasUsed := big.NewInt(int64(10000 + i)) + + // Encode the non indexed event data + encodedData, err := executionStateEvent.Inputs.NonIndexed().Pack( + messageHash, + state, + returnData, + gasUsed, + ) + require.NoError(b, err) + + // Topics (event signature and indexed fields) + topics := [][]byte{ + executionStateEventSig[:], // Event signature + logpoller.EvmWord(sourceChainSelector).Bytes(), // Indexed sourceChainSelector + logpoller.EvmWord(sequenceNumber).Bytes(), // Indexed sequenceNumber + messageID[:], // Indexed messageId + } + + // Create log entry + logs = append(logs, logpoller.Log{ + EvmChainId: ubig.New(big.NewInt(0).SetUint64(uint64(destChain))), + LogIndex: logIndex, + BlockHash: utils.NewHash(), + BlockNumber: blockNumber, + BlockTimestamp: time.Now(), + EventSig: executionStateEventSig, + Topics: topics, + Address: executionStateEventAddress, + TxHash: utils.NewHash(), + Data: encodedData, + CreatedAt: time.Now(), + }) + } + + // Insert logs into the database + require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) + require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfEvents), time.Now(), int64(offset+numOfEvents))) +} + +// Benchmark Results: +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 13729 85838 ns/op 43473 B/op 647 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 870 1405208 ns/op 1156315 B/op 21102 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 90 12129488 ns/op 10833395 B/op 201076 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 10 105741438 ns/op 49103282 B/op 796213 allocs/op +func Benchmark_CCIPReader_MessageSentRanges(b *testing.B) { + tests := []struct { + logsInserted int + startSeqNum cciptypes.SeqNum + endSeqNum cciptypes.SeqNum + }{ + {0, 0, 10}, // No logs + {10, 0, 9}, // Get all messages with 10 logs + {100, 0, 100}, // Get all messages with 100 logs + {100_000, 100_000 - 256, 100_000}, // Get the last 256 messages + } + + for _, tt := range tests { + b.Run(fmt.Sprintf("LogsInserted_%d_StartSeq_%d_EndSeq_%d", tt.logsInserted, tt.startSeqNum, tt.endSeqNum), func(b *testing.B) { + benchmarkMessageSentRanges(b, tt.logsInserted, tt.startSeqNum, tt.endSeqNum) + }) + } +} + +func benchmarkMessageSentRanges(b *testing.B, logsInserted int, startSeqNum, endSeqNum cciptypes.SeqNum) { + // Initialize test setup + ctx := tests.Context(b) + s := setupMsgsBetweenSeqNumsTest(ctx, b, true) + expectedRangeLen := calculateExpectedRangeLen(logsInserted, startSeqNum, endSeqNum) + + err := s.extendedCR.Bind(ctx, []types.BoundContract{ + { + Address: s.contractAddr.String(), + Name: consts.ContractNameOnRamp, + }, + }) + require.NoError(b, err) + + // Insert logs if needed + if logsInserted > 0 { + populateDatabaseForMessageSent(ctx, b, s, chainS1, chainD, logsInserted, 0) + } + + // Reset timer to measure only the query time + b.ResetTimer() + + for i := 0; i < b.N; i++ { + msgs, err := s.reader.MsgsBetweenSeqNums( + ctx, + chainS1, + cciptypes.NewSeqNumRange(startSeqNum, endSeqNum), + ) + require.NoError(b, err) + require.Len(b, msgs, expectedRangeLen) + } +} + +func populateDatabaseForMessageSent( + ctx context.Context, + b *testing.B, + testEnv *testSetupData, + sourceChain cciptypes.ChainSelector, + destChain cciptypes.ChainSelector, + numOfEvents int, + offset int, +) { + var logs []logpoller.Log + messageSentEvent, exists := onrampABI.Events[consts.EventNameCCIPMessageSent] + require.True(b, exists, "Event CCIPMessageSent not found in ABI") + + messageSentEventSig := messageSentEvent.ID + messageSentEventAddress := testEnv.contractAddr + + for i := 0; i < numOfEvents; i++ { + // Calculate unique BlockNumber and LogIndex + blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers + logIndex := int64(offset + i + 1) // Offset ensures unique log indices + + // Populate fields for the event + destChainSelector := uint64(destChain) + // #nosec G115 + sequenceNumber := uint64(offset + i) + + // Create InternalRampMessageHeader struct + header := onramp.InternalRampMessageHeader{ + MessageId: utils.NewHash(), + SourceChainSelector: uint64(sourceChain), + DestChainSelector: destChainSelector, + SequenceNumber: sequenceNumber, + // #nosec G115 + Nonce: uint64(i), + } + + // Create InternalEVM2AnyTokenTransfer slice + tokenTransfers := []onramp.InternalEVM2AnyTokenTransfer{ + { + SourcePoolAddress: utils.RandomAddress(), + DestTokenAddress: []byte{0x01, 0x02}, + ExtraData: []byte{0x03}, + // #nosec G115 + Amount: big.NewInt(1000 + int64(i)), + DestExecData: []byte{}, + }, + } + + // Create InternalEVM2AnyRampMessage struct + message := onramp.InternalEVM2AnyRampMessage{ + Header: header, + Sender: utils.RandomAddress(), + Data: []byte{0x04, 0x05}, + Receiver: []byte{0x06, 0x07}, + ExtraArgs: []byte{0x08}, + FeeToken: utils.RandomAddress(), + // #nosec G115 + FeeTokenAmount: big.NewInt(2000 + int64(i)), + // #nosec G115 + + FeeValueJuels: big.NewInt(3000 + int64(i)), + TokenAmounts: tokenTransfers, + } + + // Encode the non-indexed event data + encodedData, err := messageSentEvent.Inputs.NonIndexed().Pack( + message, + ) + require.NoError(b, err) + + // Topics (event signature and indexed fields) + topics := [][]byte{ + messageSentEventSig[:], // Event signature + logpoller.EvmWord(destChainSelector).Bytes(), // Indexed destChainSelector + logpoller.EvmWord(sequenceNumber).Bytes(), // Indexed sequenceNumber + } + + // Create log entry + logs = append(logs, logpoller.Log{ + EvmChainId: ubig.New(big.NewInt(0).SetUint64(uint64(sourceChain))), + LogIndex: logIndex, + BlockHash: utils.NewHash(), + BlockNumber: blockNumber, + BlockTimestamp: time.Now(), + EventSig: messageSentEventSig, + Topics: topics, + Address: messageSentEventAddress, + TxHash: utils.NewHash(), + Data: encodedData, + CreatedAt: time.Now(), + }) + } + + // Insert logs into the database + require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) + require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfEvents), time.Now(), int64(offset+numOfEvents))) +} + +func calculateExpectedRangeLen(logsInserted int, startSeq, endSeq cciptypes.SeqNum) int { + if logsInserted == 0 { + return 0 + } + start := uint64(startSeq) + end := uint64(endSeq) + // #nosec G115 + logs := uint64(logsInserted) + + if start >= logs { + return 0 + } + + if end >= logs { + end = logs - 1 + } + + // #nosec G115 + return int(end - start + 1) +} + +func setupSimulatedBackendAndAuth(t testing.TB) (*simulated.Backend, *bind.TransactOpts) { + privateKey, err := crypto.GenerateKey() + require.NoError(t, err) + + blnc, ok := big.NewInt(0).SetString("999999999999999999999999999999999999", 10) + require.True(t, ok) + + alloc := map[common.Address]ethtypes.Account{crypto.PubkeyToAddress(privateKey.PublicKey): {Balance: blnc}} + simulatedBackend := simulated.NewBackend(alloc, simulated.WithBlockGasLimit(8000000)) + + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337)) + require.NoError(t, err) + auth.GasLimit = uint64(6000000) + + return simulatedBackend, auth +} + +func testSetupRealContracts( + ctx context.Context, + t *testing.T, + destChain uint64, + toBindContracts map[cciptypes.ChainSelector][]types.BoundContract, + toMockBindings map[cciptypes.ChainSelector][]types.BoundContract, + env changeset.DeployedEnv, +) ccipreaderpkg.CCIPReader { + db := pgtest.NewSqlxDB(t) + lpOpts := logpoller.Opts{ + PollPeriod: time.Millisecond, + FinalityDepth: 0, + BackfillBatchSize: 10, + RpcBatchSize: 10, + KeepFinalizedBlocksDepth: 100000, + } + lggr := logger.TestLogger(t) + lggr.SetLogLevel(zapcore.ErrorLevel) + + var crs = make(map[cciptypes.ChainSelector]contractreader.Extended) + for chain, bindings := range toBindContracts { + be := env.Env.Chains[uint64(chain)].Client.(*memory.Backend) + cl := client.NewSimulatedBackendClient(t, be.Sim, big.NewInt(0).SetUint64(uint64(chain))) + headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(chain)), db, lggr), + cl, + lggr, + headTracker, + lpOpts, + ) + require.NoError(t, lp.Start(ctx)) + + var cfg evmtypes.ChainReaderConfig + if chain == cs(destChain) { + cfg = evmconfig.DestReaderConfig + } else { + cfg = evmconfig.SourceReaderConfig + } + cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, cfg) + require.NoError(t, err) + + extendedCr2 := contractreader.NewExtendedContractReader(cr) + err = extendedCr2.Bind(ctx, bindings) + require.NoError(t, err) + crs[cciptypes.ChainSelector(chain)] = extendedCr2 + + err = cr.Start(ctx) + require.NoError(t, err) + + t.Cleanup(func() { + require.NoError(t, cr.Close()) + require.NoError(t, lp.Close()) + require.NoError(t, db.Close()) + }) + } + + for chain, bindings := range toMockBindings { + if _, ok := crs[chain]; ok { + require.False(t, ok, "chain %d already exists", chain) + } + m := readermocks.NewMockContractReaderFacade(t) + m.EXPECT().Bind(ctx, bindings).Return(nil) + ecr := contractreader.NewExtendedContractReader(m) + err := ecr.Bind(ctx, bindings) + require.NoError(t, err) + crs[chain] = ecr + } + + contractReaders := map[cciptypes.ChainSelector]contractreader.Extended{} + for chain, cr := range crs { + contractReaders[chain] = cr + } + contractWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) + reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, cciptypes.ChainSelector(destChain), nil) + + return reader +} + +func testSetup( + ctx context.Context, + t testing.TB, + params testSetupParams, +) *testSetupData { + address, _, _, err := ccip_reader_tester.DeployCCIPReaderTester(params.Auth, params.SimulatedBackend.Client()) + assert.NoError(t, err) + params.SimulatedBackend.Commit() + + // Setup contract client + contract, err := ccip_reader_tester.NewCCIPReaderTester(address, params.SimulatedBackend.Client()) + assert.NoError(t, err) + + lggr := logger.TestLogger(t) + lggr.SetLogLevel(zapcore.ErrorLevel) + // Parameterize database selection + var db *sqlx.DB + if params.UseHeavyDB { + _, db = heavyweight.FullTestDBV2(t, nil) // Heavyweight database for benchmarks + } else { + db = pgtest.NewSqlxDB(t) // Simple in-memory DB for tests + } + lpOpts := logpoller.Opts{ + PollPeriod: time.Millisecond, + FinalityDepth: params.FinalityDepth, + BackfillBatchSize: 10, + RpcBatchSize: 10, + KeepFinalizedBlocksDepth: 100000, + } + cl := client.NewSimulatedBackendClient(t, params.SimulatedBackend, big.NewInt(0).SetUint64(uint64(params.ReaderChain))) + headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + orm := logpoller.NewORM(big.NewInt(0).SetUint64(uint64(params.ReaderChain)), db, lggr) + lp := logpoller.NewLogPoller( + orm, + cl, + lggr, + headTracker, + lpOpts, + ) + assert.NoError(t, lp.Start(ctx)) + + for sourceChain, seqNum := range params.OnChainSeqNums { + _, err1 := contract.SetSourceChainConfig(params.Auth, uint64(sourceChain), ccip_reader_tester.OffRampSourceChainConfig{ + IsEnabled: true, + MinSeqNr: uint64(seqNum), + OnRamp: utils.RandomAddress().Bytes(), + }) + assert.NoError(t, err1) + params.SimulatedBackend.Commit() + scc, err1 := contract.GetSourceChainConfig(&bind.CallOpts{Context: ctx}, uint64(sourceChain)) + assert.NoError(t, err1) + assert.Equal(t, seqNum, cciptypes.SeqNum(scc.MinSeqNr)) + } + + cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, params.Cfg) + require.NoError(t, err) + + extendedCr := contractreader.NewExtendedContractReader(cr) + + if params.BindTester { + err = extendedCr.Bind(ctx, []types.BoundContract{ + { + Address: address.String(), + Name: params.ContractNameToBind, + }, + }) + require.NoError(t, err) + } + + var otherCrs = make(map[cciptypes.ChainSelector]contractreader.Extended) + for chain, bindings := range params.ToBindContracts { + cl2 := client.NewSimulatedBackendClient(t, params.SimulatedBackend, big.NewInt(0).SetUint64(uint64(chain))) + headTracker2 := headtracker.NewSimulatedHeadTracker(cl2, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp2 := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(chain)), db, lggr), + cl2, + lggr, + headTracker2, + lpOpts, + ) + require.NoError(t, lp2.Start(ctx)) + + cr2, err2 := evm.NewChainReaderService(ctx, lggr, lp2, headTracker2, cl2, params.Cfg) + require.NoError(t, err2) + + extendedCr2 := contractreader.NewExtendedContractReader(cr2) + err2 = extendedCr2.Bind(ctx, bindings) + require.NoError(t, err2) + otherCrs[chain] = extendedCr2 + } + + for chain, bindings := range params.ToMockBindings { + if _, ok := otherCrs[chain]; ok { + require.False(t, ok, "chain %d already exists", chain) + } + m := readermocks.NewMockContractReaderFacade(t) + m.EXPECT().Bind(ctx, bindings).Return(nil) + ecr := contractreader.NewExtendedContractReader(m) + err = ecr.Bind(ctx, bindings) + require.NoError(t, err) + otherCrs[chain] = ecr + } + + err = cr.Start(ctx) + require.NoError(t, err) + + contractReaders := map[cciptypes.ChainSelector]contractreader.Extended{params.ReaderChain: extendedCr} + for chain, cr := range otherCrs { + contractReaders[chain] = cr + } + contractWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) + reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, params.DestChain, nil) + + t.Cleanup(func() { + require.NoError(t, cr.Close()) + require.NoError(t, lp.Close()) + require.NoError(t, db.Close()) + }) + + return &testSetupData{ + contractAddr: address, + contract: contract, + sb: params.SimulatedBackend, + auth: params.Auth, + orm: orm, + lp: lp, + cl: cl, + reader: reader, + extendedCR: extendedCr, + } +} + +type testSetupParams struct { + ReaderChain cciptypes.ChainSelector + DestChain cciptypes.ChainSelector + OnChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum + Cfg evmtypes.ChainReaderConfig + ToBindContracts map[cciptypes.ChainSelector][]types.BoundContract + ToMockBindings map[cciptypes.ChainSelector][]types.BoundContract + BindTester bool + ContractNameToBind string + SimulatedBackend *simulated.Backend + Auth *bind.TransactOpts + FinalityDepth int64 + UseHeavyDB bool +} + +type testSetupData struct { + contractAddr common.Address + contract *ccip_reader_tester.CCIPReaderTester + sb *simulated.Backend + auth *bind.TransactOpts + orm logpoller.ORM + lp logpoller.LogPoller + cl client.Client + reader ccipreaderpkg.CCIPReader + extendedCR contractreader.Extended +} + +func cs(i uint64) cciptypes.ChainSelector { + return cciptypes.ChainSelector(i) +} diff --git a/integration-tests/example.env b/integration-tests/example.env index 35db6263644..fbc9a76091e 100644 --- a/integration-tests/example.env +++ b/integration-tests/example.env @@ -3,6 +3,7 @@ ########## General Test Settings ########## export CHAINLINK_ENV_USER="Satoshi-Nakamoto" # Name of the person running the tests (change to your own) +export CHAINLINK_USER_TEAM="My awesome team" # Name of the team you are running the test for (change to your own) export TEST_LOG_LEVEL="info" # info | debug | trace ########## Soak/Chaos/Load Test Specific Settings ########## @@ -16,6 +17,7 @@ export SLACK_API_KEY="xoxb-example-key" # API key used to report soak test resul export SLACK_CHANNEL="C000000000" # Channel ID for the slack bot to post test results export SLACK_USER="U000000000" # User ID of the person running the soak tests to properly notify them +##### ---- applicable only, when using legacy EVMClient ---- ##### ########## Network Settings ########## # General EVM Settings, used only for quick prototyping when using GENERAL as the SELECTED_NETWORK export EVM_NAME="General EVM" diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 7d07aa27a24..f4e6a9720e8 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -1,6 +1,8 @@ module github.com/smartcontractkit/chainlink/integration-tests -go 1.23 +go 1.23.3 + +toolchain go1.23.4 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../ @@ -11,6 +13,7 @@ require ( dario.cat/mergo v1.0.1 github.com/AlekSi/pointer v1.1.0 github.com/Masterminds/semver/v3 v3.3.0 + github.com/avast/retry-go v3.0.0+incompatible github.com/avast/retry-go/v4 v4.6.0 github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a @@ -35,17 +38,18 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/slack-go/slack v0.15.0 github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 - github.com/smartcontractkit/chain-selectors v1.0.31 + github.com/smartcontractkit/chain-selectors v1.0.34 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f + github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 - github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 - github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241106193309-5560cd76211a + github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241120195829-bd7a1943ad07 github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 @@ -85,6 +89,8 @@ require ( github.com/CosmWasm/wasmd v0.40.1 // indirect github.com/CosmWasm/wasmvm v1.2.4 // indirect github.com/DataDog/zstd v1.5.2 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 // indirect github.com/Khan/genqlient v0.7.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect @@ -99,7 +105,6 @@ require ( github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect - github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect github.com/aws/aws-sdk-go v1.54.19 // indirect github.com/aws/aws-sdk-go-v2 v1.32.2 // indirect @@ -257,6 +262,7 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/googleapis/gax-go/v2 v2.14.0 // indirect github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/securecookie v1.1.2 // indirect @@ -332,7 +338,7 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a // indirect + github.com/leanovate/gopter v0.2.11 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect @@ -413,17 +419,16 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect - github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 // indirect - github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect - github.com/smartcontractkit/wsrpc v0.8.2 // indirect + github.com/smartcontractkit/wsrpc v0.8.3 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -506,9 +511,10 @@ require ( golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect + google.golang.org/api v0.205.0 // indirect google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/protobuf v1.35.1 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 65c46274f61..9e0e176190d 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -16,12 +16,17 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= -cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ= -cloud.google.com/go/auth v0.9.9/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= -cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI= -cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= +cloud.google.com/go/auth v0.10.1 h1:TnK46qldSfHWt2a0b/hciaiVJsmDXWy9FqyUan0uYiI= +cloud.google.com/go/auth v0.10.1/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= +cloud.google.com/go/auth/oauth2adapt v0.2.5 h1:2p29+dePqsCHPP1bqDJcKj4qxRyYCcbzKpFyKGt3MTk= +cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -29,8 +34,8 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v1.28.1 h1:XwPcZjgMCnU2tkwY10VleUjSAfpTj9RDn+kGrbYsi8o= -cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= -cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= +cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= @@ -115,12 +120,12 @@ github.com/Depado/ginprom v1.8.0 h1:zaaibRLNI1dMiiuj1MKzatm8qrcHzikMlCc1anqOdyo= github.com/Depado/ginprom v1.8.0/go.mod h1:XBaKzeNBqPF4vxJpNLincSQZeMDnZp1tIbU0FU0UKgg= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3 h1:cb3br57K508pQEFgBxn9GDhPS9HefpyMPK1RzmtMNzk= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3 h1:xir5X8TS8UBVPWg2jHL+cSTf0jZgqYQSA54TscSt1/0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3/go.mod h1:SsdWig2J5PMnfMvfJuEb1uZa8Y+kvNyvrULFo69gTFk= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.3 h1:2vcVkrNdSMJpoOVAWi9ApsQR5iqNeFGt5Qx8Xlt3IoI= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.3/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 h1:GYUJLfvd++4DMuMhCFLgLXvFwofIxh/qOwoGuS/LTew= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Khan/genqlient v0.7.0 h1:GZ1meyRnzcDTK48EjqB8t3bcfYvHArCUUvgOwpz1D4w= @@ -255,6 +260,7 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= @@ -262,10 +268,10 @@ github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/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= @@ -326,6 +332,7 @@ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= @@ -377,6 +384,7 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= @@ -481,7 +489,9 @@ github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -669,6 +679,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -730,6 +741,7 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -739,12 +751,16 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= @@ -753,15 +769,16 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= -github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= +github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= +github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= github.com/gophercloud/gophercloud v1.13.0 h1:8iY9d1DAbzMW6Vok1AxbbK5ZaUjzMp0tdyt4fX9IeJ0= github.com/gophercloud/gophercloud v1.13.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= @@ -1033,6 +1050,7 @@ github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -1045,8 +1063,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= -github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -1073,6 +1091,7 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 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= @@ -1192,6 +1211,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= @@ -1248,6 +1269,7 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= @@ -1268,6 +1290,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1388,43 +1411,47 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 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.15.0 h1:LE2lj2y9vqqiOf+qIIy0GvEoxgF1N5yLGZffmEZykt0= github.com/slack-go/slack v0.15.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= -github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm3KUgyMDyK0v0aOtUk4= -github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= +github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc h1:2xPgOrBA7Zjjulcn31Bp6q0kOrONbEnII7iE/vSQVHk= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d h1:0tnjo1gpG16PHAouXamgDAAu6e7PWaM0Ppq6dMWnjx0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57 h1:1BMTG66HnCIz+KMBWGvyzELNM6VHGwv2WKFhN7H49Sg= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57/go.mod h1:QPiorgpbLv4+Jn4YO6xxU4ftTu4T3QN8HwX3ImP59DE= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db/go.mod h1:yjb9d4q7+m8aGbjfTbkNoNuA4PeSxcUszsSZHDrvS0E= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969 h1:M/SMFCY4URO0H1eB9r3pkRv0LS3Ofxk/GapSgGrLfFI= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969/go.mod h1:mGmRvlk54ufCufV4EBWizOGtXoXfePoFAuYEVC8EwdY= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtOAzKS4PrPIiJX65BGo1aYiYZxFVEW+jc= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 h1:lvn9Yxah+QD1/PcgijLO0dNRa28HuQWZl8Kkxh46KJc= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 h1:GDGrC5OGiV0RyM1znYWehSQXyZQWTOzrEeJRYmysPCE= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2/go.mod h1:DsT43c1oTBmp3iQkMcoZOoKThwZvt8X3Pz6UmznJ4GY= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 h1:Fw2F8fKa5QdOUzLAj6Y/EB6XFC0QtK2pw5bqQSatL4A= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 h1:a3xetGZh2nFO1iX5xd9OuqiCkgbWLvW6fTN6fgVubPo= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 h1:yB1x5UXvpZNka+5h57yo1/GrKfXKCqMzChCISpldZx4= @@ -1439,10 +1466,12 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= -github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= +github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= @@ -1454,6 +1483,7 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1462,15 +1492,18 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= @@ -1609,10 +1642,13 @@ go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYr go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= @@ -1625,6 +1661,7 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/collector/pdata v1.12.0 h1:Xx5VK1p4VO0md8MWm2icwC1MnJ7f8EimKItMWw46BmA= @@ -1702,6 +1739,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -1761,6 +1799,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1769,9 +1808,12 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1811,8 +1853,11 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -1826,6 +1871,7 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= @@ -1834,6 +1880,13 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -1903,17 +1956,23 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1950,6 +2009,7 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= @@ -1965,6 +2025,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= @@ -2025,12 +2086,19 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2063,8 +2131,14 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.202.0 h1:y1iuVHMqokQbimW79ZqPZWo4CiyFu6HcCYHwSNyzlfo= -google.golang.org/api v0.202.0/go.mod h1:3Jjeq7M/SFblTNCp7ES2xhq+WvGL0KeXI0joHQBfwTQ= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/api v0.205.0 h1:LFaxkAIpDb/GsrWV20dMMo5MR0h8UARTbn24LmD+0Pg= +google.golang.org/api v0.205.0/go.mod h1:NrK1EMqO8Xk6l6QwRAmrXXg2v6dzukhlOyvkYtnvUuc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2108,13 +2182,24 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4= -google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= -google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38/go.mod h1:vuAjtvlwkDKF6L1GQ0SokiRLCGFfeBUXWr/aFFkHACc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2130,9 +2215,14 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/stats/opentelemetry v0.0.0-20241022174616-4bb0170ac65f h1:TsfHqsKI7qhOoYugDRyFDSKAuzegDVmkSCpjUyLkb+8= @@ -2168,6 +2258,7 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index 65f1d21257a..823c1bd8825 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -196,6 +196,12 @@ Load Config: loadDuration := time.Duration(*loadedTestConfig.Automation.General.Duration) * time.Second automationDefaultLinkFunds := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(10000))) //10000 LINK + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(string(tc.Automation), testType) + require.NoError(t, err, "Error creating required chain.link labels for namespace") + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(string(tc.Automation), testType) + require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") + testEnvironment := environment.New(&environment.Config{ TTL: loadDuration.Round(time.Hour) + time.Hour, NamespacePrefix: fmt.Sprintf( @@ -203,6 +209,9 @@ Load Config: testType, strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-"), ), + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, Test: t, PreventPodEviction: true, }) diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 7a6e8ed6247..23f840a67f3 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -1,6 +1,8 @@ module github.com/smartcontractkit/chainlink/load-tests -go 1.23 +go 1.23.3 + +toolchain go1.23.4 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../../ @@ -17,13 +19,13 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d - github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 - github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 + github.com/smartcontractkit/chainlink/deployment v0.0.0-20241120141814-47da13e86197 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241030133659-9ec788e78b4f - github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241106193309-5560cd76211a + github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241120195829-bd7a1943ad07 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de github.com/stretchr/testify v1.9.0 github.com/wiremock/go-wiremock v1.9.0 @@ -310,7 +312,7 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a // indirect + github.com/leanovate/gopter v0.2.11 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect @@ -397,21 +399,21 @@ require ( github.com/shoenig/test v0.6.6 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chain-selectors v1.0.31 // indirect + github.com/smartcontractkit/chain-selectors v1.0.34 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect - github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect - github.com/smartcontractkit/wsrpc v0.8.2 // indirect + github.com/smartcontractkit/wsrpc v0.8.3 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -505,8 +507,8 @@ require ( gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.35.1 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 127b2074b3f..e9eaaf81dad 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -16,6 +16,11 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ= @@ -115,12 +120,12 @@ github.com/Depado/ginprom v1.8.0 h1:zaaibRLNI1dMiiuj1MKzatm8qrcHzikMlCc1anqOdyo= github.com/Depado/ginprom v1.8.0/go.mod h1:XBaKzeNBqPF4vxJpNLincSQZeMDnZp1tIbU0FU0UKgg= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3 h1:cb3br57K508pQEFgBxn9GDhPS9HefpyMPK1RzmtMNzk= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3 h1:xir5X8TS8UBVPWg2jHL+cSTf0jZgqYQSA54TscSt1/0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3/go.mod h1:SsdWig2J5PMnfMvfJuEb1uZa8Y+kvNyvrULFo69gTFk= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.3 h1:2vcVkrNdSMJpoOVAWi9ApsQR5iqNeFGt5Qx8Xlt3IoI= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.3/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 h1:GYUJLfvd++4DMuMhCFLgLXvFwofIxh/qOwoGuS/LTew= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/K-Phoen/grabana v0.22.2 h1:tMiSvcKHnDbXi3IgBCax2+sg5qL6x0G6wMURHgjGDag= @@ -259,6 +264,7 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= @@ -266,10 +272,10 @@ github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/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= @@ -320,6 +326,7 @@ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= @@ -371,6 +378,7 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= @@ -475,7 +483,9 @@ github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -663,6 +673,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -724,6 +735,7 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -733,6 +745,10 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= @@ -751,11 +767,12 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfF github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= -github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= +github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= +github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= github.com/gophercloud/gophercloud v1.13.0 h1:8iY9d1DAbzMW6Vok1AxbbK5ZaUjzMp0tdyt4fX9IeJ0= github.com/gophercloud/gophercloud v1.13.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= @@ -1029,6 +1046,7 @@ github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -1041,8 +1059,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= -github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -1067,6 +1085,7 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 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= @@ -1182,6 +1201,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= @@ -1238,6 +1259,7 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= @@ -1258,6 +1280,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1379,39 +1402,47 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 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.15.0 h1:LE2lj2y9vqqiOf+qIIy0GvEoxgF1N5yLGZffmEZykt0= github.com/slack-go/slack v0.15.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm3KUgyMDyK0v0aOtUk4= -github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= +github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= +github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc h1:2xPgOrBA7Zjjulcn31Bp6q0kOrONbEnII7iE/vSQVHk= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241129093748-80df27514efc/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d h1:0tnjo1gpG16PHAouXamgDAAu6e7PWaM0Ppq6dMWnjx0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57 h1:1BMTG66HnCIz+KMBWGvyzELNM6VHGwv2WKFhN7H49Sg= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241114154055-8d29ea018b57/go.mod h1:QPiorgpbLv4+Jn4YO6xxU4ftTu4T3QN8HwX3ImP59DE= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db/go.mod h1:yjb9d4q7+m8aGbjfTbkNoNuA4PeSxcUszsSZHDrvS0E= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969 h1:M/SMFCY4URO0H1eB9r3pkRv0LS3Ofxk/GapSgGrLfFI= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241118190857-e2db20a6a969/go.mod h1:mGmRvlk54ufCufV4EBWizOGtXoXfePoFAuYEVC8EwdY= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= +github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtOAzKS4PrPIiJX65BGo1aYiYZxFVEW+jc= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 h1:lvn9Yxah+QD1/PcgijLO0dNRa28HuQWZl8Kkxh46KJc= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 h1:GDGrC5OGiV0RyM1znYWehSQXyZQWTOzrEeJRYmysPCE= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2/go.mod h1:DsT43c1oTBmp3iQkMcoZOoKThwZvt8X3Pz6UmznJ4GY= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 h1:Fw2F8fKa5QdOUzLAj6Y/EB6XFC0QtK2pw5bqQSatL4A= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 h1:a3xetGZh2nFO1iX5xd9OuqiCkgbWLvW6fTN6fgVubPo= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 h1:yB1x5UXvpZNka+5h57yo1/GrKfXKCqMzChCISpldZx4= @@ -1426,10 +1457,12 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= -github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= +github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= @@ -1441,6 +1474,7 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1449,15 +1483,18 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= @@ -1596,10 +1633,13 @@ go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYr go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= @@ -1612,6 +1652,7 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/collector/pdata v1.12.0 h1:Xx5VK1p4VO0md8MWm2icwC1MnJ7f8EimKItMWw46BmA= @@ -1689,6 +1730,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -1748,6 +1790,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1756,9 +1799,12 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1798,8 +1844,11 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -1813,6 +1862,7 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= @@ -1821,6 +1871,13 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -1889,17 +1946,23 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1935,6 +1998,7 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= @@ -1950,6 +2014,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= @@ -2010,12 +2075,19 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2048,8 +2120,14 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.202.0 h1:y1iuVHMqokQbimW79ZqPZWo4CiyFu6HcCYHwSNyzlfo= -google.golang.org/api v0.202.0/go.mod h1:3Jjeq7M/SFblTNCp7ES2xhq+WvGL0KeXI0joHQBfwTQ= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/api v0.205.0 h1:LFaxkAIpDb/GsrWV20dMMo5MR0h8UARTbn24LmD+0Pg= +google.golang.org/api v0.205.0/go.mod h1:NrK1EMqO8Xk6l6QwRAmrXXg2v6dzukhlOyvkYtnvUuc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2093,13 +2171,24 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4= -google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= -google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38/go.mod h1:vuAjtvlwkDKF6L1GQ0SokiRLCGFfeBUXWr/aFFkHACc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2115,9 +2204,14 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/stats/opentelemetry v0.0.0-20241022174616-4bb0170ac65f h1:TsfHqsKI7qhOoYugDRyFDSKAuzegDVmkSCpjUyLkb+8= @@ -2153,6 +2247,7 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= diff --git a/integration-tests/smoke/ccip/ccip_batching_test.go b/integration-tests/smoke/ccip/ccip_batching_test.go index 864e01c2007..8c3615fbb20 100644 --- a/integration-tests/smoke/ccip/ccip_batching_test.go +++ b/integration-tests/smoke/ccip/ccip_batching_test.go @@ -9,20 +9,15 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" "golang.org/x/exp/maps" - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -30,16 +25,33 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" ) -func Test_CCIPBatching(t *testing.T) { +const ( + numMessages = 40 +) + +type batchTestSetup struct { + e changeset.DeployedEnv + state changeset.CCIPOnChainState + sourceChain1 uint64 + sourceChain2 uint64 + destChain uint64 +} + +func newBatchTestSetup(t *testing.T) batchTestSetup { // Setup 3 chains, with 2 lanes going to the dest. - lggr := logger.TestLogger(t) - ctx := changeset.Context(t) - // Will load 3 chains when specified by the overrides.toml or env vars (E2E_TEST_SELECTED_NETWORK). - // See e2e-tests.yml. - e, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, &changeset.TestConfigs{ - IsUSDC: false, - IsMultiCall3: true, // needed for this test - }) + e := changeset.NewMemoryEnvironmentWithJobsAndContracts( + t, + logger.TestLogger(t), + memory.MemoryEnvironmentConfig{ + Chains: 3, + Nodes: 4, + Bootstraps: 1, + NumOfUsersPerChain: 2, + }, + &changeset.TestConfigs{ + IsMultiCall3: true, + }, + ) state, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) @@ -61,248 +73,260 @@ func Test_CCIPBatching(t *testing.T) { require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(e.Env, state, sourceChain1, destChain, false)) require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(e.Env, state, sourceChain2, destChain, false)) - const ( - numMessages = 5 - ) + return batchTestSetup{e, state, sourceChain1, sourceChain2, destChain} +} + +func Test_CCIPBatching_MaxBatchSizeEVM(t *testing.T) { + t.Parallel() + + ctx := changeset.Context(t) + setup := newBatchTestSetup(t) + sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state + var ( startSeqNum = map[uint64]ccipocr3.SeqNum{ sourceChain1: 1, sourceChain2: 1, } - ) - - t.Run("batch data only messages from single source", func(t *testing.T) { - var ( - sourceChain = sourceChain1 - ) - err := sendMessages( - ctx, - t, - e.Env.Chains[sourceChain], + sourceChain = sourceChain1 + transactors = []*bind.TransactOpts{ e.Env.Chains[sourceChain].DeployerKey, - state.Chains[sourceChain].OnRamp, - state.Chains[sourceChain].Router, - state.Chains[sourceChain].Multicall3, - destChain, - numMessages, - common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), - ) - require.NoError(t, err) - - _, err = changeset.ConfirmCommitWithExpectedSeqNumRange( - t, - e.Env.Chains[sourceChain], - e.Env.Chains[destChain], - state.Chains[destChain].OffRamp, - nil, - ccipocr3.NewSeqNumRange(startSeqNum[sourceChain], startSeqNum[sourceChain]+numMessages-1), - ) - require.NoErrorf(t, err, "failed to confirm commit from chain %d", sourceChain) - - states, err := changeset.ConfirmExecWithSeqNrs( - t, - e.Env.Chains[sourceChain], - e.Env.Chains[destChain], - state.Chains[destChain].OffRamp, - nil, - genSeqNrRange(startSeqNum[sourceChain], startSeqNum[sourceChain]+numMessages-1), - ) - require.NoError(t, err) - // assert that all states are successful - for _, state := range states { - require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, state) + e.Env.Chains[sourceChain].Users[0], } + errs = make(chan error, len(transactors)) + ) - startSeqNum[sourceChain] = startSeqNum[sourceChain] + numMessages - }) - - t.Run("batch data only messages from multiple sources", func(t *testing.T) { - var ( - wg sync.WaitGroup - sourceChains = []uint64{sourceChain1, sourceChain2} - errs = make(chan error, len(sourceChains)) - ) - - for _, srcChain := range sourceChains { - wg.Add(1) - go sendMessagesAsync( + for _, transactor := range transactors { + go func() { + err := sendMessages( ctx, t, - e, - state, - srcChain, + e.Env.Chains[sourceChain], + transactor, + state.Chains[sourceChain].OnRamp, + state.Chains[sourceChain].Router, + state.Chains[sourceChain].Multicall3, destChain, - numMessages, - &wg, - errs, + merklemulti.MaxNumberTreeLeaves/2, + common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), ) - } - - wg.Wait() - - var i int - for i < len(sourceChains) { - select { - case err := <-errs: - require.NoError(t, err) - i++ - case <-ctx.Done(): - require.FailNow(t, "didn't get all errors before test context was done") - } - } + t.Log("sendMessages error:", err, ", writing to channel") + errs <- err + t.Log("sent error to channel") + }() + } - // confirm the commit reports - outputErrs := make(chan outputErr[*offramp.OffRampCommitReportAccepted], len(sourceChains)) - for _, srcChain := range sourceChains { - wg.Add(1) - go assertCommitReportsAsync( - t, - e, - state, - srcChain, - destChain, - startSeqNum[srcChain], - startSeqNum[srcChain]+ccipocr3.SeqNum(numMessages)-1, - &wg, - outputErrs, - ) + var i = 0 + for i < len(transactors) { + select { + case err := <-errs: + require.NoError(t, err) + i++ + case <-ctx.Done(): + require.FailNow(t, "didn't get all errors before test context was done") } + } - t.Log("waiting for commit report") - wg.Wait() - - i = 0 - var reports []*offramp.OffRampCommitReportAccepted - for i < len(sourceChains) { - select { - case outputErr := <-outputErrs: - require.NoError(t, outputErr.err) - reports = append(reports, outputErr.output) - i++ - case <-ctx.Done(): - require.FailNow(t, "didn't get all commit reports before test context was done") - } - } + _, err := changeset.ConfirmCommitWithExpectedSeqNumRange( + t, + e.Env.Chains[sourceChain], + e.Env.Chains[destChain], + state.Chains[destChain].OffRamp, + nil, // startBlock + ccipocr3.NewSeqNumRange( + startSeqNum[sourceChain], + startSeqNum[sourceChain]+ccipocr3.SeqNum(merklemulti.MaxNumberTreeLeaves)-1, + ), + true, + ) + require.NoErrorf(t, err, "failed to confirm commit from chain %d", sourceChain) +} - // the reports should be the same for both, since both roots should be batched within - // that one report. - require.Lenf(t, reports, len(sourceChains), "expected %d commit reports", len(sourceChains)) - require.NotNil(t, reports[0], "commit report should not be nil") - require.NotNil(t, reports[1], "commit report should not be nil") - // TODO: this assertion is failing, despite messages being sent at the same time. - // require.Equal(t, reports[0], reports[1], "commit reports should be the same") - - // confirm execution - execErrs := make(chan outputErr[map[uint64]int], len(sourceChains)) - for _, srcChain := range sourceChains { - wg.Add(1) - go assertExecAsync( - t, - e, - state, - srcChain, - destChain, - genSeqNrRange(startSeqNum[srcChain], startSeqNum[srcChain]+ccipocr3.SeqNum(numMessages)-1), - &wg, - execErrs, - ) - } +func Test_CCIPBatching_MultiSource(t *testing.T) { + // t.Skip("Exec not working, boosting not working correctly") - t.Log("waiting for exec reports") - wg.Wait() - - i = 0 - var execStates []map[uint64]int - for i < len(sourceChains) { - select { - case outputErr := <-execErrs: - require.NoError(t, outputErr.err) - execStates = append(execStates, outputErr.output) - i++ - case <-ctx.Done(): - require.FailNow(t, "didn't get all exec reports before test context was done") - } - } + t.Parallel() - // assert that all states are successful - for _, states := range execStates { - for _, state := range states { - require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, state) - } - } + // Setup 3 chains, with 2 lanes going to the dest. + ctx := changeset.Context(t) + setup := newBatchTestSetup(t) + sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state - // update the start and end seq nums - for _, srcChain := range sourceChains { - startSeqNum[srcChain] = startSeqNum[srcChain] + numMessages + var ( + wg sync.WaitGroup + sourceChains = []uint64{sourceChain1, sourceChain2} + errs = make(chan error, len(sourceChains)) + startSeqNum = map[uint64]ccipocr3.SeqNum{ + sourceChain1: 1, + sourceChain2: 1, } - }) - - t.Run("max evm batch size", func(t *testing.T) { - t.Skipf("This test is flaky, skipping until the issue related to fee calculation is resolved") - var ( - sourceChain = sourceChain1 - otherSender = mustNewTransactor(t, e.Env.Chains[sourceChain]) - transactors = []*bind.TransactOpts{ - e.Env.Chains[sourceChain].DeployerKey, - otherSender, - } - errs = make(chan error, len(transactors)) - ) + ) - // transfer some eth to the other sender from the DeployerKey - sendEth( + for _, srcChain := range sourceChains { + wg.Add(1) + go sendMessagesAsync( ctx, t, - e.Env.Chains[sourceChain], - e.Env.Chains[sourceChain].DeployerKey, - otherSender.From, - assets.Ether(20).ToInt(), + e, + state, + srcChain, + destChain, + numMessages, + &wg, + errs, ) + } - for _, transactor := range transactors { - go func() { - err := sendMessages( - ctx, - t, - e.Env.Chains[sourceChain], - transactor, - state.Chains[sourceChain].OnRamp, - state.Chains[sourceChain].Router, - state.Chains[sourceChain].Multicall3, - destChain, - merklemulti.MaxNumberTreeLeaves/2, - common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), - ) - t.Log("sendMessages error:", err, ", writing to channel") - errs <- err - t.Log("sent error to channel") - }() + wg.Wait() + + var i int + for i < len(sourceChains) { + select { + case err := <-errs: + require.NoError(t, err) + i++ + case <-ctx.Done(): + require.FailNow(t, "didn't get all errors before test context was done") } + } - var i = 0 - for i < len(transactors) { - select { - case err := <-errs: - require.NoError(t, err) - i++ - case <-ctx.Done(): - require.FailNow(t, "didn't get all errors before test context was done") - } + // confirm the commit reports + outputErrs := make(chan outputErr[*offramp.OffRampCommitReportAccepted], len(sourceChains)) + for _, srcChain := range sourceChains { + wg.Add(1) + go assertCommitReportsAsync( + t, + e, + state, + srcChain, + destChain, + startSeqNum[srcChain], + startSeqNum[srcChain]+ccipocr3.SeqNum(numMessages)-1, + &wg, + outputErrs, + ) + } + + t.Log("waiting for commit report") + wg.Wait() + + i = 0 + var reports []*offramp.OffRampCommitReportAccepted + for i < len(sourceChains) { + select { + case outputErr := <-outputErrs: + require.NoError(t, outputErr.err) + reports = append(reports, outputErr.output) + i++ + case <-ctx.Done(): + require.FailNow(t, "didn't get all commit reports before test context was done") } + } - _, err = changeset.ConfirmCommitWithExpectedSeqNumRange( + // the reports should be the same for both, since both roots should be batched within + // that one report. + require.Lenf(t, reports, len(sourceChains), "expected %d commit reports", len(sourceChains)) + require.NotNil(t, reports[0], "commit report should not be nil") + require.NotNil(t, reports[1], "commit report should not be nil") + // TODO: this assertion is failing, despite messages being sent at the same time. + // require.Equal(t, reports[0], reports[1], "commit reports should be the same") + + // confirm execution + execErrs := make(chan outputErr[map[uint64]int], len(sourceChains)) + for _, srcChain := range sourceChains { + wg.Add(1) + go assertExecAsync( t, - e.Env.Chains[sourceChain], - e.Env.Chains[destChain], - state.Chains[destChain].OffRamp, - nil, // startBlock - ccipocr3.NewSeqNumRange( - startSeqNum[sourceChain], - startSeqNum[sourceChain]+ccipocr3.SeqNum(merklemulti.MaxNumberTreeLeaves)-1, - ), + e, + state, + srcChain, + destChain, + genSeqNrRange(startSeqNum[srcChain], startSeqNum[srcChain]+ccipocr3.SeqNum(numMessages)-1), + &wg, + execErrs, ) - require.NoErrorf(t, err, "failed to confirm commit from chain %d", sourceChain) - }) + } + + t.Log("waiting for exec reports") + wg.Wait() + + i = 0 + var execStates []map[uint64]int + for i < len(sourceChains) { + select { + case outputErr := <-execErrs: + require.NoError(t, outputErr.err) + execStates = append(execStates, outputErr.output) + i++ + case <-ctx.Done(): + require.FailNow(t, "didn't get all exec reports before test context was done") + } + } + + // assert that all states are successful + for _, states := range execStates { + for _, state := range states { + require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, state) + } + } +} + +func Test_CCIPBatching_SingleSource(t *testing.T) { + t.Parallel() + + // Setup 3 chains, with 2 lanes going to the dest. + ctx := changeset.Context(t) + setup := newBatchTestSetup(t) + sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state + + var ( + startSeqNum = map[uint64]ccipocr3.SeqNum{ + sourceChain1: 1, + sourceChain2: 1, + } + ) + + var ( + sourceChain = sourceChain1 + ) + err := sendMessages( + ctx, + t, + e.Env.Chains[sourceChain], + e.Env.Chains[sourceChain].DeployerKey, + state.Chains[sourceChain].OnRamp, + state.Chains[sourceChain].Router, + state.Chains[sourceChain].Multicall3, + destChain, + numMessages, + common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), + ) + require.NoError(t, err) + + _, err = changeset.ConfirmCommitWithExpectedSeqNumRange( + t, + e.Env.Chains[sourceChain], + e.Env.Chains[destChain], + state.Chains[destChain].OffRamp, + nil, + ccipocr3.NewSeqNumRange(startSeqNum[sourceChain], startSeqNum[sourceChain]+numMessages-1), + true, + ) + require.NoErrorf(t, err, "failed to confirm commit from chain %d", sourceChain) + + states, err := changeset.ConfirmExecWithSeqNrs( + t, + e.Env.Chains[sourceChain], + e.Env.Chains[destChain], + state.Chains[destChain].OffRamp, + nil, + genSeqNrRange(startSeqNum[sourceChain], startSeqNum[sourceChain]+numMessages-1), + ) + require.NoError(t, err) + // assert that all states are successful + for _, state := range states { + require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, state) + } } type outputErr[T any] struct { @@ -352,6 +376,7 @@ func assertCommitReportsAsync( state.Chains[destChainSelector].OffRamp, nil, ccipocr3.NewSeqNumRange(startSeqNum, endSeqNum), + true, ) errs <- outputErr[*offramp.OffRampCommitReportAccepted]{commitReport, err} @@ -369,18 +394,34 @@ func sendMessagesAsync( out chan<- error, ) { defer wg.Done() - err := sendMessages( - ctx, - t, - e.Env.Chains[sourceChainSelector], - e.Env.Chains[sourceChainSelector].DeployerKey, - state.Chains[sourceChainSelector].OnRamp, - state.Chains[sourceChainSelector].Router, - state.Chains[sourceChainSelector].Multicall3, - destChainSelector, - numMessages, - common.LeftPadBytes(state.Chains[destChainSelector].Receiver.Address().Bytes(), 32), + var err error + + const ( + numRetries = 3 ) + + // we retry a bunch of times just in case there is a race b/w the prices being + // posted and the messages being sent. + for i := 0; i < numRetries; i++ { + err = sendMessages( + ctx, + t, + e.Env.Chains[sourceChainSelector], + e.Env.Chains[sourceChainSelector].DeployerKey, + state.Chains[sourceChainSelector].OnRamp, + state.Chains[sourceChainSelector].Router, + state.Chains[sourceChainSelector].Multicall3, + destChainSelector, + numMessages, + common.LeftPadBytes(state.Chains[destChainSelector].Receiver.Address().Bytes(), 32), + ) + if err == nil { + break + } + + t.Log("sendMessagesAsync error is non-nil:", err, ", retrying") + } + t.Log("sendMessagesAsync error:", err, ", writing to channel") out <- err } @@ -408,8 +449,13 @@ func sendMessages( return fmt.Errorf("generate messages: %w", err) } + currBalance, err := sourceChain.Client.BalanceAt(ctx, sourceTransactOpts.From, nil) + if err != nil { + return fmt.Errorf("get balance: %w", err) + } + // Send the tx with the messages through the multicall - t.Logf("Sending %d messages with total value %s", numMessages, totalValue.String()) + t.Logf("Sending %d messages with total value %s, current balance: %s", numMessages, totalValue.String(), currBalance.String()) tx, err := sourceMulticall3.Aggregate3Value( &bind.TransactOpts{ From: sourceTransactOpts.From, @@ -430,7 +476,9 @@ func sendMessages( if err != nil { return fmt.Errorf("get message sent event: %w", err) } - defer iter.Close() + defer func() { + require.NoError(t, iter.Close()) + }() // there should be numMessages messages emitted for i := 0; i < numMessages; i++ { @@ -457,7 +505,7 @@ func genMessages( Data: []byte(fmt.Sprintf("hello world %d", i)), TokenAmounts: nil, FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, + ExtraArgs: changeset.MakeEVMExtraArgsV2(50_000, false), } fee, err := sourceRouter.GetFee(&bind.CallOpts{Context: ctx}, destChainSelector, msg) @@ -491,51 +539,3 @@ func genSeqNrRange(start, end ccipocr3.SeqNum) []uint64 { } return seqNrs } - -func mustNewTransactor(t *testing.T, chain deployment.Chain) *bind.TransactOpts { - chainID, err := chainsel.GetChainIDFromSelector(chain.Selector) - require.NoError(t, err) - chainIDBig, ok := new(big.Int).SetString(chainID, 10) - require.True(t, ok, "evm chainID must be integral") - key, err := crypto.GenerateKey() - require.NoError(t, err) - transactor, err := bind.NewKeyedTransactorWithChainID(key, chainIDBig) - require.NoError(t, err) - return transactor -} - -func sendEth( - ctx context.Context, - t *testing.T, - chain deployment.Chain, - from *bind.TransactOpts, - to common.Address, - value *big.Int, -) { - balance, err := chain.Client.BalanceAt(ctx, from.From, nil) - require.NoError(t, err) - if balance.Cmp(value) < 0 { - t.Fatalf("insufficient balance: %s < %s", balance.String(), value.String()) - } - t.Logf("balance of from account %s: %s", from.From.String(), balance.String()) - - nonce, err := chain.Client.PendingNonceAt(ctx, from.From) - require.NoError(t, err) - gp, err := chain.Client.SuggestGasPrice(ctx) - require.NoError(t, err) - tx := gethtypes.NewTx(&gethtypes.LegacyTx{ - Nonce: nonce, - GasPrice: gp, - Gas: 21_000, - To: &to, - Value: value, - Data: nil, - }) - signedTx, err := from.Signer(from.From, tx) - require.NoError(t, err) - err = chain.Client.SendTransaction(ctx, signedTx) - require.NoError(t, err) - t.Log("sent funding tx:", signedTx.Hash().Hex()) - _, err = deployment.ConfirmIfNoError(chain, signedTx, err) - require.NoError(t, err) -} diff --git a/integration-tests/smoke/ccip/ccip_fee_boosting_test.go b/integration-tests/smoke/ccip/ccip_fee_boosting_test.go new file mode 100644 index 00000000000..1fe9d5817c9 --- /dev/null +++ b/integration-tests/smoke/ccip/ccip_fee_boosting_test.go @@ -0,0 +1,334 @@ +package smoke + +import ( + "context" + "fmt" + "math/big" + "testing" + "time" + + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/test-go/testify/require" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +var ( + linkPrice = deployment.E18Mult(100) + wethPrice = deployment.E18Mult(4000) +) + +func Test_CCIPFeeBoosting(t *testing.T) { + e := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), + memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + }, &changeset.TestConfigs{ + OCRConfigOverride: func(params changeset.CCIPOCRParams) changeset.CCIPOCRParams { + // Only 1 boost (=OCR round) is enough to cover the fee + params.ExecuteOffChainConfig.RelativeBoostPerWaitHour = 10 + // Disable token price updates + params.CommitOffChainConfig.TokenPriceBatchWriteFrequency = *config.MustNewDuration(1_000_000 * time.Hour) + // Disable gas price updates + params.CommitOffChainConfig.RemoteGasPriceBatchWriteFrequency = *config.MustNewDuration(1_000_000 * time.Hour) + // Disable token price updates + params.CommitOffChainConfig.TokenInfo = nil + return params + }, + }) + + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + + allChainSelectors := maps.Keys(e.Env.Chains) + require.Len(t, allChainSelectors, 2) + sourceChain := allChainSelectors[0] + destChain := allChainSelectors[1] + t.Log("All chain selectors:", allChainSelectors, + ", home chain selector:", e.HomeChainSel, + ", feed chain selector:", e.FeedChainSel, + ", source chain selector:", sourceChain, + ", dest chain selector:", destChain, + ) + + fetchedGasPriceDest, err := e.Env.Chains[destChain].Client.SuggestGasPrice(tests.Context(t)) + require.NoError(t, err) + originalGasPriceDestUSD := new(big.Int).Div( + new(big.Int).Mul(fetchedGasPriceDest, wethPrice), + big.NewInt(1e18), + ) + t.Log("Gas price on dest chain (USD):", originalGasPriceDestUSD) + + // Adjust destination gas price on source fee quoter to 95% of the current value + adjustedGasPriceDest := + new(big.Int).Div( + new(big.Int).Mul(originalGasPriceDestUSD, big.NewInt(95)), + big.NewInt(100), + ) + t.Log("Adjusted gas price on dest chain:", adjustedGasPriceDest) + + initialPrices := changeset.InitialPrices{ + LinkPrice: linkPrice, + WethPrice: wethPrice, + GasPrice: changeset.ToPackedFee(adjustedGasPriceDest, big.NewInt(0)), + } + + laneCfg := changeset.LaneConfig{ + SourceSelector: sourceChain, + DestSelector: destChain, + InitialPricesBySource: initialPrices, + FeeQuoterDestChain: changeset.DefaultFeeQuoterDestChainConfig(), + TestRouter: false, + } + + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.AddLanes), + Config: changeset.AddLanesConfig{LaneConfigs: []changeset.LaneConfig{laneCfg}}, + }, + }) + require.NoError(t, err) + + // Update token prices in destination chain FeeQuoter + err = updateTokensPrices(e, state, destChain, map[common.Address]*big.Int{ + state.Chains[destChain].LinkToken.Address(): linkPrice, + state.Chains[destChain].Weth9.Address(): wethPrice, + }) + require.NoError(t, err) + + startBlocks := make(map[uint64]*uint64) + expectedSeqNum := make(map[changeset.SourceDestPair]uint64) + expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) + + latesthdr, err := e.Env.Chains[sourceChain].Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + msgSentEvent := changeset.TestSendRequest(t, e.Env, state, sourceChain, destChain, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), + Data: []byte("message that needs fee boosting"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + startBlocks[sourceChain] = &block + expectedSeqNum[changeset.SourceDestPair{ + SourceChainSelector: sourceChain, + DestChainSelector: destChain, + }] = msgSentEvent.SequenceNumber + expectedSeqNumExec[changeset.SourceDestPair{ + SourceChainSelector: sourceChain, + DestChainSelector: destChain, + }] = []uint64{msgSentEvent.SequenceNumber} + + err = updateGasPrice(e, state, sourceChain, destChain, originalGasPriceDestUSD) + require.NoError(t, err) + + // Confirm gas prices are updated + srcFeeQuoter := state.Chains[sourceChain].FeeQuoter + err = changeset.ConfirmGasPriceUpdated(t, e.Env.Chains[destChain], srcFeeQuoter, 0, originalGasPriceDestUSD) + require.NoError(t, err) + + // Confirm that fee boosting will be triggered + require.True(t, willTriggerFeeBoosting(t, msgSentEvent, state, sourceChain, destChain)) + + // hack + time.Sleep(30 * time.Second) + replayBlocks := make(map[uint64]uint64) + replayBlocks[sourceChain] = 1 + replayBlocks[destChain] = 1 + changeset.ReplayLogs(t, e.Env.Offchain, replayBlocks) + + // Confirm that the message is committed and executed + changeset.ConfirmCommitForAllWithExpectedSeqNums(t, e.Env, state, expectedSeqNum, startBlocks) + changeset.ConfirmExecWithSeqNrsForAll(t, e.Env, state, expectedSeqNumExec, startBlocks) +} + +// TODO: Find a more accurate way to determine if fee boosting will be triggered +func willTriggerFeeBoosting( + t *testing.T, + msgSentEvent *onramp.OnRampCCIPMessageSent, + state changeset.CCIPOnChainState, + srcChain, destChain uint64) bool { + msg := convertToMessage(msgSentEvent.Message) + t.Log("\n=== Fee Boosting Analysis ===") + t.Logf("Src Chain: %d", msg.Header.SourceChainSelector) + t.Logf("Dest Chain: %d", msg.Header.DestChainSelector) + + ep := ccipevm.NewGasEstimateProvider() + chainState, exists := state.Chains[srcChain] + require.True(t, exists) + feeQuoter := chainState.FeeQuoter + + premium, err := feeQuoter.GetPremiumMultiplierWeiPerEth(&bind.CallOpts{Context: context.Background()}, chainState.Weth9.Address()) + require.NoError(t, err) + t.Logf("Premium: %d", premium) + + // Get LINK price + linkPrice, err := feeQuoter.GetTokenPrice(&bind.CallOpts{Context: context.Background()}, chainState.LinkToken.Address()) + require.NoError(t, err) + t.Logf("LINK Price: %s", linkPrice.Value.String()) + t.Logf("Juels in message: %s", msg.FeeValueJuels.String()) + + // Calculate fee in USD token + fee := new(big.Int).Div( + new(big.Int).Mul(linkPrice.Value, msg.FeeValueJuels.Int), + new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil), + ) + t.Logf("Fee paid (in USD token): %s", fee.String()) + + // Calculate message gas + messageGas := new(big.Int).SetUint64(ep.CalculateMessageMaxGas(msg)) + t.Logf("Estimated message gas: %s", messageGas.String()) + + // Get token and gas prices + nativeTokenAddress := chainState.Weth9.Address() + tokenAndGasPrice, err := feeQuoter.GetTokenAndGasPrices(&bind.CallOpts{Context: context.Background()}, nativeTokenAddress, destChain) + require.NoError(t, err) + t.Logf("Raw gas price (uint224): %s for chain: %d", tokenAndGasPrice.GasPriceValue.String(), destChain) + + // Extract uint112 gas price + gasPrice, err := convertGasPriceToUint112(tokenAndGasPrice.GasPriceValue) + require.NoError(t, err) + t.Logf("Extracted gas price (uint112): %s", gasPrice.String()) + t.Logf("Native token price: %s", tokenAndGasPrice.TokenPrice.String()) + + // Calculate total execution cost + execCost := new(big.Int).Mul(messageGas, gasPrice) + t.Logf("Total execution cost: %s", execCost.String()) + + // Check if fee boosting will trigger + willBoost := execCost.Cmp(fee) > 0 + t.Logf("\nWill fee boosting trigger? %v", willBoost) + t.Logf("Execution cost / Fee ratio: %.2f", + new(big.Float).Quo( + new(big.Float).SetInt(execCost), + new(big.Float).SetInt(fee), + ), + ) + + return execCost.Cmp(fee) > 0 +} + +func convertGasPriceToUint112(gasPrice *big.Int) (*big.Int, error) { + // Create a mask for uint112 (112 bits of 1s) + mask := new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 112), big.NewInt(1)) + + // Extract the lower 112 bits using AND operation + result := new(big.Int).And(gasPrice, mask) + + return result, nil +} + +func convertToMessage(msg onramp.InternalEVM2AnyRampMessage) cciptypes.Message { + // Convert header + header := cciptypes.RampMessageHeader{ + MessageID: cciptypes.Bytes32(msg.Header.MessageId), + SourceChainSelector: cciptypes.ChainSelector(msg.Header.SourceChainSelector), + DestChainSelector: cciptypes.ChainSelector(msg.Header.DestChainSelector), + SequenceNumber: cciptypes.SeqNum(msg.Header.SequenceNumber), + Nonce: msg.Header.Nonce, + } + + // Convert token amounts + tokenAmounts := make([]cciptypes.RampTokenAmount, len(msg.TokenAmounts)) + for i, ta := range msg.TokenAmounts { + tokenAmounts[i] = cciptypes.RampTokenAmount{ + SourcePoolAddress: cciptypes.UnknownAddress(ta.SourcePoolAddress.Bytes()), + DestTokenAddress: cciptypes.UnknownAddress(ta.DestTokenAddress), + ExtraData: cciptypes.Bytes(ta.ExtraData), + Amount: cciptypes.BigInt{Int: ta.Amount}, + DestExecData: cciptypes.Bytes(ta.DestExecData), + } + } + + return cciptypes.Message{ + Header: header, + Sender: cciptypes.UnknownAddress(msg.Sender.Bytes()), + Data: cciptypes.Bytes(msg.Data), + Receiver: cciptypes.UnknownAddress(msg.Receiver), + ExtraArgs: cciptypes.Bytes(msg.ExtraArgs), + FeeToken: cciptypes.UnknownAddress(msg.FeeToken.Bytes()), + FeeTokenAmount: cciptypes.BigInt{Int: msg.FeeTokenAmount}, + FeeValueJuels: cciptypes.BigInt{Int: msg.FeeValueJuels}, + TokenAmounts: tokenAmounts, + } +} + +func updateGasPrice(env changeset.DeployedEnv, state changeset.CCIPOnChainState, srcChain, destChain uint64, gasPrice *big.Int) error { + chainState, exists := state.Chains[srcChain] + if !exists { + return fmt.Errorf("chain state not found for selector: %d", srcChain) + } + + feeQuoter := chainState.FeeQuoter + // Update gas price + auth := env.Env.Chains[srcChain].DeployerKey + tx, err := feeQuoter.UpdatePrices(auth, fee_quoter.InternalPriceUpdates{ + TokenPriceUpdates: nil, + GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ + { + DestChainSelector: destChain, + UsdPerUnitGas: gasPrice, + }, + }, + }) + if err != nil { + return errors.Wrapf(err, "updating gas price on chain %d", srcChain) + } + if _, err := deployment.ConfirmIfNoError(env.Env.Chains[srcChain], tx, err); err != nil { + return err + } + + return nil +} + +func updateTokensPrices(env changeset.DeployedEnv, state changeset.CCIPOnChainState, chain uint64, tokenPrices map[common.Address]*big.Int) error { + chainState, exists := state.Chains[chain] + if !exists { + return fmt.Errorf("chain state not found for selector: %d", chain) + } + + feeQuoter := chainState.FeeQuoter + // Update token prices + auth := env.Env.Chains[chain].DeployerKey + tokenPricesUpdates := make([]fee_quoter.InternalTokenPriceUpdate, 0, len(tokenPrices)) + for token, price := range tokenPrices { + tokenPricesUpdates = append(tokenPricesUpdates, fee_quoter.InternalTokenPriceUpdate{ + SourceToken: token, + UsdPerToken: price, + }) + } + tx, err := feeQuoter.UpdatePrices(auth, fee_quoter.InternalPriceUpdates{ + TokenPriceUpdates: tokenPricesUpdates, + GasPriceUpdates: nil, + }) + if err != nil { + return errors.Wrapf(err, "updating token prices on chain %d", chain) + } + if _, err := deployment.ConfirmIfNoError(env.Env.Chains[chain], tx, err); err != nil { + return err + } + + return nil +} diff --git a/integration-tests/smoke/ccip/ccip_fees_test.go b/integration-tests/smoke/ccip/ccip_fees_test.go new file mode 100644 index 00000000000..791ba8f2619 --- /dev/null +++ b/integration-tests/smoke/ccip/ccip_fees_test.go @@ -0,0 +1,459 @@ +package smoke + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/weth9_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +// setupTokens deploys transferable tokens on the source and dest, mints tokens for the source and dest, and +// approves the router to spend the tokens +func setupTokens( + t *testing.T, + state changeset.CCIPOnChainState, + tenv changeset.DeployedEnv, + src, dest uint64, + transferTokenMintAmount, + feeTokenMintAmount *big.Int, +) ( + srcToken *burn_mint_erc677.BurnMintERC677, + dstToken *burn_mint_erc677.BurnMintERC677, +) { + lggr := logger.TestLogger(t) + e := tenv.Env + + // Deploy the token to test transferring + srcToken, _, dstToken, _, err := changeset.DeployTransferableToken( + lggr, + tenv.Env.Chains, + src, + dest, + tenv.Env.Chains[src].DeployerKey, + tenv.Env.Chains[dest].DeployerKey, + state, + tenv.Env.ExistingAddresses, + "MY_TOKEN", + ) + require.NoError(t, err) + + linkToken := state.Chains[src].LinkToken + + tx, err := srcToken.Mint( + e.Chains[src].DeployerKey, + e.Chains[src].DeployerKey.From, + transferTokenMintAmount, + ) + _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) + require.NoError(t, err) + + // Mint a destination token + tx, err = dstToken.Mint( + e.Chains[dest].DeployerKey, + e.Chains[dest].DeployerKey.From, + transferTokenMintAmount, + ) + _, err = deployment.ConfirmIfNoError(e.Chains[dest], tx, err) + require.NoError(t, err) + + // Approve the router to spend the tokens and confirm the tx's + // To prevent having to approve the router for every transfer, we approve a sufficiently large amount + tx, err = srcToken.Approve(e.Chains[src].DeployerKey, state.Chains[src].Router.Address(), math.MaxBig256) + _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) + require.NoError(t, err) + + tx, err = dstToken.Approve(e.Chains[dest].DeployerKey, state.Chains[dest].Router.Address(), math.MaxBig256) + _, err = deployment.ConfirmIfNoError(e.Chains[dest], tx, err) + require.NoError(t, err) + + // Grant mint and burn roles to the deployer key for the newly deployed linkToken + // Since those roles are not granted automatically + tx, err = linkToken.GrantMintAndBurnRoles(e.Chains[src].DeployerKey, e.Chains[src].DeployerKey.From) + _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) + require.NoError(t, err) + + // Mint link token and confirm the tx + tx, err = linkToken.Mint( + e.Chains[src].DeployerKey, + e.Chains[src].DeployerKey.From, + feeTokenMintAmount, + ) + _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) + require.NoError(t, err) + + return srcToken, dstToken +} + +func Test_CCIPFees(t *testing.T) { + t.Parallel() + tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + }, nil) + e := tenv.Env + + allChains := tenv.Env.AllChainSelectors() + require.Len(t, allChains, 2, "need two chains for this test") + sourceChain := allChains[0] + destChain := allChains[1] + + // Get new state after migration. + state, err := changeset.LoadOnchainState(e) + require.NoError(t, err) + + srcToken, dstToken := setupTokens( + t, + state, + tenv, + sourceChain, + destChain, + deployment.E18Mult(10_000), + deployment.E18Mult(10_000), + ) + + // Ensure capreg logs are up to date. + changeset.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + + // Add all lanes + require.NoError(t, changeset.AddLanesForAll(e, state)) + + t.Run("Send programmable token transfer pay with Link token", func(t *testing.T) { + runFeeTokenTestCase(feeTokenTestCase{ + t: t, + dst: destChain, + src: sourceChain, + env: tenv, + tokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: srcToken.Address(), + Amount: deployment.E18Mult(2), + }, + }, + feeToken: state.Chains[sourceChain].LinkToken.Address(), + data: []byte("hello ptt world"), + receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), + srcToken: srcToken, + dstToken: dstToken, + assertTokenBalance: true, + }) + }) + + t.Run("Send programmable token transfer pay with native", func(t *testing.T) { + runFeeTokenTestCase(feeTokenTestCase{ + t: t, + + // note the order of src and dest is reversed here + src: destChain, + dst: sourceChain, + + env: tenv, + tokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: dstToken.Address(), + Amount: deployment.E18Mult(2), + }, + }, + feeToken: common.HexToAddress("0x0"), + data: []byte("hello ptt world"), + receiver: common.LeftPadBytes(state.Chains[sourceChain].Receiver.Address().Bytes(), 32), + + // note the order of src and dest is reversed here + srcToken: dstToken, + dstToken: srcToken, + assertTokenBalance: true, + }) + }) + + t.Run("Send programmable token transfer pay with wrapped native", func(t *testing.T) { + runFeeTokenTestCase(feeTokenTestCase{ + t: t, + src: sourceChain, + dst: destChain, + env: tenv, + tokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: srcToken.Address(), + Amount: deployment.E18Mult(2), + }, + }, + feeToken: state.Chains[sourceChain].Weth9.Address(), + data: []byte("hello ptt world"), + receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), + srcToken: srcToken, + dstToken: dstToken, + assertTokenBalance: true, + }) + }) + + t.Run("Send programmable token transfer but revert not enough tokens", func(t *testing.T) { + // Send to the receiver on the destination chain paying with LINK token + var ( + receiver = common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32) + data = []byte("") + feeToken = state.Chains[sourceChain].LinkToken.Address() + ) + + // Increase the token send amount to more than available to intentionally cause a revert + ccipMessage := router.ClientEVM2AnyMessage{ + Receiver: receiver, + Data: data, + TokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: srcToken.Address(), + Amount: deployment.E18Mult(100_000_000), + }, + }, + FeeToken: feeToken, + ExtraArgs: nil, + } + + _, _, err = changeset.CCIPSendRequest( + e, + state, + &changeset.CCIPSendReqConfig{ + Sender: e.Chains[sourceChain].DeployerKey, + IsTestRouter: true, + SourceChain: sourceChain, + DestChain: destChain, + Evm2AnyMessage: ccipMessage, + }, + ) + require.Error(t, err) + }) + + t.Run("Send data-only message pay with link token", func(t *testing.T) { + runFeeTokenTestCase(feeTokenTestCase{ + t: t, + src: sourceChain, + dst: destChain, + env: tenv, + // no tokens, only data + tokenAmounts: nil, + feeToken: state.Chains[sourceChain].LinkToken.Address(), + data: []byte("hello link world"), + receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), + srcToken: srcToken, + dstToken: dstToken, + assertTokenBalance: false, + }) + }) + + t.Run("Send message pay with native", func(t *testing.T) { + runFeeTokenTestCase(feeTokenTestCase{ + t: t, + src: sourceChain, + dst: destChain, + env: tenv, + // no tokens, only data + tokenAmounts: nil, + feeToken: common.HexToAddress("0x0"), + data: []byte("hello native world"), + receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), + srcToken: srcToken, + dstToken: dstToken, + assertTokenBalance: false, + }) + }) + + t.Run("Send message pay with wrapped native", func(t *testing.T) { + runFeeTokenTestCase(feeTokenTestCase{ + t: t, + src: sourceChain, + dst: destChain, + env: tenv, + // no tokens, only data + tokenAmounts: nil, + feeToken: state.Chains[sourceChain].Weth9.Address(), + data: []byte("hello wrapped native world"), + receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), + srcToken: srcToken, + dstToken: dstToken, + assertTokenBalance: false, + }) + }) +} + +type feeTokenTestCase struct { + t *testing.T + src, dst uint64 + env changeset.DeployedEnv + srcToken, dstToken *burn_mint_erc677.BurnMintERC677 + tokenAmounts []router.ClientEVMTokenAmount + feeToken common.Address + receiver []byte + data []byte + assertTokenBalance bool +} + +func runFeeTokenTestCase(tc feeTokenTestCase) { + ctx := tests.Context(tc.t) + // Need to keep track of the block number for each chain so that event subscription can be done from that block. + startBlocks := make(map[uint64]*uint64) + expectedSeqNum := make(map[changeset.SourceDestPair]uint64) + expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) + + srcChain := tc.env.Env.Chains[tc.src] + dstChain := tc.env.Env.Chains[tc.dst] + + state, err := changeset.LoadOnchainState(tc.env.Env) + require.NoError(tc.t, err) + + var dstTokBalanceBefore *big.Int + if tc.assertTokenBalance { + var err error + dstTokBalanceBefore, err = tc.dstToken.BalanceOf(nil, state.Chains[tc.dst].Receiver.Address()) + require.NoError(tc.t, err) + tc.t.Logf("destination token balance before of receiver %s: %s", + state.Chains[tc.dst].Receiver.Address(), + dstTokBalanceBefore.String()) + } + + // if fee token is not native then approve the router to spend the fee token from the sender. + var feeTokenWrapper *burn_mint_erc677.BurnMintERC677 + if tc.feeToken != common.HexToAddress("0x0") { + if tc.feeToken == state.Chains[tc.src].Weth9.Address() { + // Deposit some ETH into the WETH contract + weth9, err := weth9_wrapper.NewWETH9(state.Chains[tc.src].Weth9.Address(), srcChain.Client) + require.NoError(tc.t, err) + + balance, err := srcChain.Client.BalanceAt(ctx, srcChain.DeployerKey.From, nil) + require.NoError(tc.t, err) + + tc.t.Logf("balance before deposit: %s", balance.String()) + + srcChain.DeployerKey.Value = assets.Ether(100).ToInt() + tx, err := weth9.Deposit(srcChain.DeployerKey) + _, err = deployment.ConfirmIfNoError(srcChain, tx, err) + require.NoError(tc.t, err) + srcChain.DeployerKey.Value = big.NewInt(0) + } + + var err error + feeTokenWrapper, err = burn_mint_erc677.NewBurnMintERC677(tc.feeToken, srcChain.Client) + require.NoError(tc.t, err) + + // Approve the router to spend fee token + tx, err := feeTokenWrapper.Approve(srcChain.DeployerKey, state.Chains[tc.src].Router.Address(), math.MaxBig256) + + _, err = deployment.ConfirmIfNoError(srcChain, tx, err) + require.NoError(tc.t, err) + } + + // get the header for the destination chain and the relevant block number + latesthdr, err := dstChain.Client.HeaderByNumber(testcontext.Get(tc.t), nil) + require.NoError(tc.t, err) + block := latesthdr.Number.Uint64() + startBlocks[tc.dst] = &block + + // Get the fee Token Balance Before, if not fee token set get native balance. + var feeTokenBalanceBefore *big.Int + if feeTokenWrapper != nil { + feeTokenBalanceBefore, err = feeTokenWrapper.BalanceOf(&bind.CallOpts{ + Context: ctx, + }, srcChain.DeployerKey.From) + require.NoError(tc.t, err) + } else { + feeTokenBalanceBefore, err = srcChain.Client.BalanceAt(ctx, srcChain.DeployerKey.From, nil) + require.NoError(tc.t, err) + } + tc.t.Logf("fee token balance before: %s, fee token enabled: %s", + feeTokenBalanceBefore.String(), tc.feeToken.String()) + + msgSentEvent := changeset.TestSendRequest( + tc.t, + tc.env.Env, + state, + tc.src, + tc.dst, + false, + router.ClientEVM2AnyMessage{ + Receiver: tc.receiver, + Data: tc.data, + TokenAmounts: tc.tokenAmounts, + FeeToken: tc.feeToken, + ExtraArgs: nil, + }, + ) + + expectedSeqNum[changeset.SourceDestPair{ + SourceChainSelector: tc.src, + DestChainSelector: tc.dst, + }] = msgSentEvent.SequenceNumber + expectedSeqNumExec[changeset.SourceDestPair{ + SourceChainSelector: tc.src, + DestChainSelector: tc.dst, + }] = []uint64{msgSentEvent.SequenceNumber} + + // Check the fee token balance after the request and ensure fee tokens were spent + var feeTokenBalanceAfter *big.Int + if feeTokenWrapper != nil { + feeTokenBalanceAfter, err = feeTokenWrapper.BalanceOf(&bind.CallOpts{ + Context: ctx, + }, srcChain.DeployerKey.From) + require.NoError(tc.t, err) + } else { + feeTokenBalanceAfter, err = srcChain.Client.BalanceAt(ctx, srcChain.DeployerKey.From, nil) + require.NoError(tc.t, err) + } + tc.t.Logf("fee token balance after: %s, fee token: %s, fee paid: %s", + feeTokenBalanceAfter.String(), tc.feeToken.String(), msgSentEvent.Message.FeeTokenAmount) + // in the case we have no fee token, native is also used to pay for the tx, + // so we have to subtract that as well + if feeTokenWrapper == nil { + receipt, err := srcChain.Client.TransactionReceipt(ctx, msgSentEvent.Raw.TxHash) + require.NoError(tc.t, err) + txCostWei := new(big.Int).Mul(new(big.Int).SetUint64(receipt.GasUsed), receipt.EffectiveGasPrice) + feeTokenBalanceBefore.Sub(feeTokenBalanceBefore, txCostWei) + } + require.Equal( + tc.t, + feeTokenBalanceAfter, + new(big.Int).Sub(feeTokenBalanceBefore, msgSentEvent.Message.FeeTokenAmount), + ) + + // Wait for all commit reports to land. + changeset.ConfirmCommitForAllWithExpectedSeqNums(tc.t, tc.env.Env, state, expectedSeqNum, startBlocks) + + // After commit is reported on all chains, token prices should be updated in FeeQuoter. + linkAddress := state.Chains[tc.dst].LinkToken.Address() + feeQuoter := state.Chains[tc.dst].FeeQuoter + timestampedPrice, err := feeQuoter.GetTokenPrice(&bind.CallOpts{ + Context: ctx, + }, linkAddress) + require.NoError(tc.t, err) + require.Equal(tc.t, changeset.MockLinkPrice, timestampedPrice.Value) + + // Wait for all exec reports to land + changeset.ConfirmExecWithSeqNrsForAll(tc.t, tc.env.Env, state, expectedSeqNumExec, startBlocks) + + if tc.assertTokenBalance { + require.Len(tc.t, tc.tokenAmounts, 1) + expectedTransferAmount := tc.tokenAmounts[0].Amount + + balanceAfter, err := tc.dstToken.BalanceOf(&bind.CallOpts{ + Context: ctx, + }, state.Chains[tc.dst].Receiver.Address()) + require.NoError(tc.t, err) + require.Equal( + tc.t, + new(big.Int).Add(dstTokBalanceBefore, expectedTransferAmount), + balanceAfter, + ) + } +} diff --git a/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go b/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go new file mode 100644 index 00000000000..221d35bd992 --- /dev/null +++ b/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go @@ -0,0 +1,126 @@ +package smoke + +import ( + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +// Test_CCIPGasPriceUpdates tests that chain fee price updates are propagated correctly when +// price reaches some deviation threshold or when the price has expired. +func Test_CCIPGasPriceUpdates(t *testing.T) { + lggr := logger.TestLogger(t) + ctx := changeset.Context(t) + callOpts := &bind.CallOpts{Context: ctx} + + var gasPriceExpiry = 5 * time.Second + e, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, &changeset.TestConfigs{ + OCRConfigOverride: func(params changeset.CCIPOCRParams) changeset.CCIPOCRParams { + params.CommitOffChainConfig.RemoteGasPriceBatchWriteFrequency = *config.MustNewDuration(gasPriceExpiry) + return params + }, + }) + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + require.NoError(t, changeset.AddLanesForAll(e.Env, state)) + + allChainSelectors := maps.Keys(e.Env.Chains) + assert.GreaterOrEqual(t, len(allChainSelectors), 2, "test requires at least 2 chains") + + sourceChain1 := allChainSelectors[0] + sourceChain2 := allChainSelectors[1] + + feeQuoter1 := state.Chains[sourceChain1].FeeQuoter + feeQuoter2 := state.Chains[sourceChain2].FeeQuoter + + // get initial chain fees + initialChain2Fee, err := feeQuoter1.GetDestinationChainGasPrice(callOpts, sourceChain2) + require.NoError(t, err) + initialChain1Fee, err := feeQuoter2.GetDestinationChainGasPrice(callOpts, sourceChain1) + require.NoError(t, err) + t.Logf("initial chain1 fee (stored in chain2): %v", initialChain1Fee) + t.Logf("initial chain2 fee (stored in chain1): %v", initialChain2Fee) + + // get latest price updates sequence number from the offRamps + offRampChain1 := state.Chains[sourceChain1].OffRamp + offRampChain2 := state.Chains[sourceChain2].OffRamp + priceUpdatesSeqNumChain1, err := offRampChain1.GetLatestPriceSequenceNumber(callOpts) + require.NoError(t, err) + priceUpdatesSeqNumChain2, err := offRampChain2.GetLatestPriceSequenceNumber(callOpts) + require.NoError(t, err) + t.Logf("priceUpdatesSeqNumChain1: %v", priceUpdatesSeqNumChain1) + t.Logf("priceUpdatesSeqNumChain2: %v", priceUpdatesSeqNumChain2) + + // update the price of chain2 + tx, err := feeQuoter1.UpdatePrices(e.Env.Chains[sourceChain1].DeployerKey, fee_quoter.InternalPriceUpdates{ + TokenPriceUpdates: nil, + GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ + {DestChainSelector: sourceChain2, UsdPerUnitGas: big.NewInt(5123)}, + }, + }) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[sourceChain1], tx, err) + require.NoError(t, err) + + // assert that the chain fees are updated by the commit plugin reports + priceDeviationChecked := false // flag to check if price deviation condition was met + assert.Eventually(t, func() bool { + // offRamps should have updated the sequence number + priceUpdatesSeqNumChain1Now, err := offRampChain1.GetLatestPriceSequenceNumber(callOpts) + require.NoError(t, err) + priceUpdatesSeqNumChain2Now, err := offRampChain2.GetLatestPriceSequenceNumber(callOpts) + require.NoError(t, err) + t.Logf("priceUpdatesSeqNumChain1: %v", priceUpdatesSeqNumChain1Now) + t.Logf("priceUpdatesSeqNumChain2: %v", priceUpdatesSeqNumChain2Now) + if priceUpdatesSeqNumChain1Now <= priceUpdatesSeqNumChain1 { + return false + } + if priceUpdatesSeqNumChain2Now <= priceUpdatesSeqNumChain2 { + return false + } + + chain2FeeNow, err := feeQuoter1.GetDestinationChainGasPrice(callOpts, sourceChain2) + require.NoError(t, err) + chain1FeeNow, err := feeQuoter2.GetDestinationChainGasPrice(callOpts, sourceChain1) + require.NoError(t, err) + t.Logf("chainFee1 (stored in chain2): %v", chain1FeeNow) + t.Logf("chainFee2 (stored in chain1): %v", chain2FeeNow) + + if !priceDeviationChecked { + // make sure there was a price update for chain2 when price deviation was reached + if chain2FeeNow.Value.Cmp(initialChain2Fee.Value) == 0 { + t.Logf("chainFee2 not updated: %v original=%v", chain2FeeNow, initialChain2Fee.Value) + return false + } + require.NotEqual(t, chain2FeeNow.Timestamp, initialChain2Fee.Timestamp) + priceDeviationChecked = true + } + + // make sure there was a price update for chain1 but with the same price - when expiration is reached + if chain1FeeNow.Timestamp == initialChain1Fee.Timestamp { + t.Logf("chainFee1 timestamp not updated: %v original=%v", chain1FeeNow, initialChain1Fee.Timestamp) + initialChain1Fee = chain1FeeNow + return false + } + if chain1FeeNow.Value.Cmp(initialChain1Fee.Value) != 0 { + t.Logf("chainFee1 changed: %v prev:%v", chain1FeeNow, initialChain1Fee.Value) + initialChain1Fee = chain1FeeNow + return false + } + + return priceDeviationChecked + }, tests.WaitTimeout(t), 500*time.Millisecond) +} diff --git a/integration-tests/smoke/ccip/ccip_message_limitations_test.go b/integration-tests/smoke/ccip/ccip_message_limitations_test.go new file mode 100644 index 00000000000..902d07aec5c --- /dev/null +++ b/integration-tests/smoke/ccip/ccip_message_limitations_test.go @@ -0,0 +1,188 @@ +package smoke + +import ( + "math/big" + "slices" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func Test_CCIPMessageLimitations(t *testing.T) { + lggr := logger.TestLogger(t) + ctx := testcontext.Get(t) + callOpts := &bind.CallOpts{Context: ctx} + + testEnv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, &changeset.TestConfigs{}) + chains := maps.Keys(testEnv.Env.Chains) + + onChainState, err := changeset.LoadOnchainState(testEnv.Env) + require.NoError(t, err) + + require.NoError(t, changeset.AddLanesForAll(testEnv.Env, onChainState)) + + srcToken, _ := setupTokens( + t, + onChainState, + testEnv, + chains[0], + chains[1], + deployment.E18Mult(10_000), + deployment.E18Mult(10_000), + ) + + chain0DestConfig, err := onChainState.Chains[chains[0]].FeeQuoter.GetDestChainConfig(callOpts, chains[1]) + require.NoError(t, err) + t.Logf("0->1 destination config: %+v", chain0DestConfig) + + testMsgs := []struct { + name string + fromChain uint64 + toChain uint64 + msg router.ClientEVM2AnyMessage + expRevert bool + }{ + { + name: "hit limit on data", + fromChain: chains[0], + toChain: chains[1], + msg: router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), + Data: []byte(strings.Repeat("0", int(chain0DestConfig.MaxDataBytes))), + FeeToken: common.HexToAddress("0x0"), + }, + }, + { + name: "hit limit on tokens", + fromChain: chains[0], + toChain: chains[1], + msg: router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), + TokenAmounts: slices.Repeat([]router.ClientEVMTokenAmount{ + {Token: srcToken.Address(), Amount: big.NewInt(1)}, + }, int(chain0DestConfig.MaxNumberOfTokensPerMsg)), + FeeToken: common.HexToAddress("0x0"), + }, + }, + { + name: "hit limit on gas limit", + fromChain: chains[0], + toChain: chains[1], + msg: router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), + Data: []byte(strings.Repeat("0", int(chain0DestConfig.MaxDataBytes))), + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: changeset.MakeEVMExtraArgsV2(uint64(chain0DestConfig.MaxPerMsgGasLimit), true), + }, + }, + //{ // TODO: exec plugin never executed this message. CCIP-4471 + // name: "hit limit on maxDataBytes, tokens, gasLimit should succeed", + // fromChain: chains[0], + // toChain: chains[1], + // msg: router.ClientEVM2AnyMessage{ + // Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), + // Data: []byte(strings.Repeat("0", int(chain0DestConfig.MaxDataBytes))), + // TokenAmounts: slices.Repeat([]router.ClientEVMTokenAmount{ + // {Token: srcToken.Address(), Amount: big.NewInt(1)}, + // }, int(chain0DestConfig.MaxNumberOfTokensPerMsg)), + // FeeToken: common.HexToAddress("0x0"), + // ExtraArgs: changeset.MakeEVMExtraArgsV2(uint64(chain0DestConfig.MaxPerMsgGasLimit), true), + // }, + //}, + { + name: "exceeding maxDataBytes", + fromChain: chains[0], + toChain: chains[1], + msg: router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), + Data: []byte(strings.Repeat("0", int(chain0DestConfig.MaxDataBytes)+1)), + TokenAmounts: []router.ClientEVMTokenAmount{}, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }, + expRevert: true, + }, + { + name: "exceeding number of tokens", + fromChain: chains[0], + toChain: chains[1], + msg: router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), + Data: []byte("abc"), + TokenAmounts: slices.Repeat([]router.ClientEVMTokenAmount{ + {Token: srcToken.Address(), Amount: big.NewInt(1)}, + }, int(chain0DestConfig.MaxNumberOfTokensPerMsg)+1), + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }, + expRevert: true, + }, + { + name: "exceeding gas limit", + fromChain: chains[0], + toChain: chains[1], + msg: router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), + Data: []byte("abc"), + TokenAmounts: []router.ClientEVMTokenAmount{}, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: changeset.MakeEVMExtraArgsV2(uint64(chain0DestConfig.MaxPerMsgGasLimit)+1, true), + }, + expRevert: true, + }, + } + + // Need to keep track of the block number for each chain so that event subscription can be done from that block. + startBlocks := make(map[uint64]*uint64) + // Send a message from each chain to every other chain. + expectedSeqNum := make(map[changeset.SourceDestPair]uint64) + expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) + for _, msg := range testMsgs { + t.Logf("Sending msg: %s", msg.name) + require.NotEqual(t, msg.fromChain, msg.toChain, "fromChain and toChain cannot be the same") + startBlocks[msg.toChain] = nil + msgSentEvent, err := changeset.DoSendRequest( + t, testEnv.Env, onChainState, + changeset.WithSourceChain(msg.fromChain), + changeset.WithDestChain(msg.toChain), + changeset.WithTestRouter(false), + changeset.WithEvm2AnyMessage(msg.msg)) + + if msg.expRevert { + t.Logf("Message reverted as expected") + require.Error(t, err) + require.Contains(t, err.Error(), "execution reverted") + continue + } + require.NoError(t, err) + + t.Logf("Message not reverted as expected") + + expectedSeqNum[changeset.SourceDestPair{ + SourceChainSelector: msg.fromChain, + DestChainSelector: msg.toChain, + }] = msgSentEvent.SequenceNumber + + expectedSeqNumExec[changeset.SourceDestPair{ + SourceChainSelector: msg.fromChain, + DestChainSelector: msg.toChain, + }] = []uint64{msgSentEvent.SequenceNumber} + } + + // Wait for all commit reports to land. + changeset.ConfirmCommitForAllWithExpectedSeqNums(t, testEnv.Env, onChainState, expectedSeqNum, startBlocks) + // Wait for all exec reports to land + changeset.ConfirmExecWithSeqNrsForAll(t, testEnv.Env, onChainState, expectedSeqNumExec, startBlocks) +} diff --git a/integration-tests/smoke/ccip/ccip_messaging_test.go b/integration-tests/smoke/ccip/ccip_messaging_test.go index 446f21898a0..07e237451c8 100644 --- a/integration-tests/smoke/ccip/ccip_messaging_test.go +++ b/integration-tests/smoke/ccip/ccip_messaging_test.go @@ -15,8 +15,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/hashutil" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -46,7 +48,11 @@ type messagingTestCaseOutput struct { func Test_CCIPMessaging(t *testing.T) { // Setup 2 chains and a single lane. ctx := changeset.Context(t) - e := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), 2, 4, nil) + e := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + }, nil) state, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) diff --git a/integration-tests/smoke/ccip/ccip_ooo_execution_test.go b/integration-tests/smoke/ccip/ccip_ooo_execution_test.go new file mode 100644 index 00000000000..86ddd07ec85 --- /dev/null +++ b/integration-tests/smoke/ccip/ccip_ooo_execution_test.go @@ -0,0 +1,273 @@ +package smoke + +import ( + "fmt" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +// Send the following messages +// 1. src -> dest - out of order token transfer to EOA +// 2. src -> dest - ordered USDC token transfer, but with faulty attestation, should be stuck forever +// 3. src -> dest - ordered token transfer, should not be executed because previous message is stuck +// 4. src -> dest - out of order message transfer, should be executed anyway +// 5. src -> dest - ordered token transfer, but from a different sender +// +// All messages should be properly committed, but only 1 and 4, 5 are fully executed. +// Messages 2 and 3 are untouched, because ordering is enforced. +func Test_OutOfOrderExecution(t *testing.T) { + lggr := logger.TestLogger(t) + ctx := tests.Context(t) + config := &changeset.TestConfigs{ + IsUSDC: true, + IsUSDCAttestationMissing: true, + } + tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + NumOfUsersPerChain: 2, + }, config) + + e := tenv.Env + state, err := changeset.LoadOnchainState(e) + require.NoError(t, err) + + allChainSelectors := maps.Keys(e.Chains) + sourceChain, destChain := allChainSelectors[0], allChainSelectors[1] + ownerSourceChain := e.Chains[sourceChain].DeployerKey + ownerDestChain := e.Chains[destChain].DeployerKey + + anotherSender, err := pickFirstAvailableUser(tenv, sourceChain, e) + require.NoError(t, err) + + oneE18 := new(big.Int).SetUint64(1e18) + + srcToken, _, destToken, _, err := changeset.DeployTransferableToken( + lggr, + tenv.Env.Chains, + sourceChain, + destChain, + ownerSourceChain, + ownerDestChain, + state, + e.ExistingAddresses, + "OWNER_TOKEN", + ) + require.NoError(t, err) + + srcUSDC, destUSDC, err := changeset.ConfigureUSDCTokenPools(lggr, e.Chains, sourceChain, destChain, state) + require.NoError(t, err) + + err = changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[sourceChain], state.Chains[sourceChain], destChain, srcUSDC) + require.NoError(t, err) + err = changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[destChain], state.Chains[destChain], sourceChain, destUSDC) + require.NoError(t, err) + + changeset.MintAndAllow( + t, + e, + state, + map[uint64][]changeset.MintTokenInfo{ + sourceChain: { + changeset.NewMintTokenInfo(ownerSourceChain, srcToken, srcUSDC), + changeset.NewMintTokenWithCustomSender(ownerSourceChain, anotherSender, srcToken), + }, + }, + ) + require.NoError(t, changeset.AddLanesForAll(e, state)) + + tokenTransfer := []router.ClientEVMTokenAmount{ + { + Token: srcToken.Address(), + Amount: oneE18, + }, + } + usdcTransfer := []router.ClientEVMTokenAmount{ + { + Token: srcUSDC.Address(), + Amount: oneE18, + }, + } + + identifier := changeset.SourceDestPair{ + SourceChainSelector: sourceChain, + DestChainSelector: destChain, + } + + startBlocks := make(map[uint64]*uint64) + expectedStatuses := make(map[uint64]int) + + latesthdr, err := e.Chains[destChain].Client.HeaderByNumber(ctx, nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + startBlocks[destChain] = &block + + // Out of order execution to the EOA should be properly executed + firstReceiver := utils.RandomAddress() + firstMessage, _ := changeset.Transfer( + ctx, + t, + e, + state, + sourceChain, + destChain, + tokenTransfer, + firstReceiver, + nil, + changeset.MakeEVMExtraArgsV2(0, true), + ) + expectedStatuses[firstMessage.SequenceNumber] = changeset.EXECUTION_STATE_SUCCESS + t.Logf("Out of order messages sent from chain %d to chain %d with sequence number %d", + sourceChain, destChain, firstMessage.SequenceNumber, + ) + + // Ordered execution should fail because attestation is not present + secondReceiver := utils.RandomAddress() + secondMsg, _ := changeset.Transfer( + ctx, + t, + e, + state, + sourceChain, + destChain, + usdcTransfer, + secondReceiver, + nil, + nil, + ) + t.Logf("Ordered USDC transfer sent from chain %d to chain %d with sequence number %d", + sourceChain, destChain, secondMsg.SequenceNumber, + ) + + // Ordered token transfer should fail, because previous message cannot be executed + thirdReceiver := utils.RandomAddress() + thirdMessage, _ := changeset.Transfer( + ctx, + t, + e, + state, + sourceChain, + destChain, + tokenTransfer, + thirdReceiver, + nil, + changeset.MakeEVMExtraArgsV2(0, false), + ) + t.Logf("Ordered token transfer from chain %d to chain %d with sequence number %d", + sourceChain, destChain, thirdMessage.SequenceNumber, + ) + + // Out of order programmable token transfer should be executed + fourthReceiver := state.Chains[destChain].Receiver.Address() + fourthMessage, _ := changeset.Transfer( + ctx, + t, + e, + state, + sourceChain, + destChain, + tokenTransfer, + fourthReceiver, + []byte("this message has enough gas to execute"), + changeset.MakeEVMExtraArgsV2(300_000, true), + ) + expectedStatuses[fourthMessage.SequenceNumber] = changeset.EXECUTION_STATE_SUCCESS + t.Logf("Out of order programmable token transfer from chain %d to chain %d with sequence number %d", + sourceChain, destChain, fourthMessage.SequenceNumber, + ) + + // Ordered token transfer, but using different sender, should be executed + fifthReceiver := utils.RandomAddress() + fifthMessage, err := changeset.DoSendRequest(t, e, state, + changeset.WithSender(anotherSender), + changeset.WithSourceChain(sourceChain), + changeset.WithDestChain(destChain), + changeset.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(fifthReceiver.Bytes(), 32), + Data: nil, + TokenAmounts: tokenTransfer, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: changeset.MakeEVMExtraArgsV2(0, false), + })) + require.NoError(t, err) + expectedStatuses[fifthMessage.SequenceNumber] = changeset.EXECUTION_STATE_SUCCESS + t.Logf("Ordered message send by %v from chain %d to chain %d with sequence number %d", + anotherSender.From, sourceChain, destChain, fifthMessage.SequenceNumber, + ) + + // All messages are committed, even these which are going to be reverted during the exec + _, err = changeset.ConfirmCommitWithExpectedSeqNumRange( + t, + e.Chains[sourceChain], + e.Chains[destChain], + state.Chains[destChain].OffRamp, + startBlocks[destChain], + ccipocr3.NewSeqNumRange( + ccipocr3.SeqNum(firstMessage.SequenceNumber), + ccipocr3.SeqNum(fifthMessage.SequenceNumber), + ), + // We don't verify batching here, so we don't need all messages to be in a single root + false, + ) + require.NoError(t, err) + + execStates := changeset.ConfirmExecWithSeqNrsForAll( + t, + e, + state, + map[changeset.SourceDestPair][]uint64{ + identifier: { + firstMessage.SequenceNumber, + fourthMessage.SequenceNumber, + fifthMessage.SequenceNumber, + }, + }, + startBlocks, + ) + require.Equal(t, expectedStatuses, execStates[identifier]) + + secondMsgState, err := state.Chains[destChain].OffRamp.GetExecutionState(&bind.CallOpts{Context: ctx}, sourceChain, secondMsg.SequenceNumber) + require.NoError(t, err) + require.Equal(t, uint8(changeset.EXECUTION_STATE_UNTOUCHED), secondMsgState) + + thirdMsgState, err := state.Chains[destChain].OffRamp.GetExecutionState(&bind.CallOpts{Context: ctx}, sourceChain, thirdMessage.SequenceNumber) + require.NoError(t, err) + require.Equal(t, uint8(changeset.EXECUTION_STATE_UNTOUCHED), thirdMsgState) + + changeset.WaitForTheTokenBalance(ctx, t, destToken.Address(), firstReceiver, e.Chains[destChain], oneE18) + changeset.WaitForTheTokenBalance(ctx, t, destUSDC.Address(), secondReceiver, e.Chains[destChain], big.NewInt(0)) + changeset.WaitForTheTokenBalance(ctx, t, destToken.Address(), thirdReceiver, e.Chains[destChain], big.NewInt(0)) + changeset.WaitForTheTokenBalance(ctx, t, destToken.Address(), fourthReceiver, e.Chains[destChain], oneE18) + changeset.WaitForTheTokenBalance(ctx, t, destToken.Address(), fifthReceiver, e.Chains[destChain], oneE18) +} + +func pickFirstAvailableUser( + tenv changeset.DeployedEnv, + sourceChain uint64, + e deployment.Environment, +) (*bind.TransactOpts, error) { + for _, user := range tenv.Users[sourceChain] { + if user == nil { + continue + } + if user.From != e.Chains[sourceChain].DeployerKey.From { + return user, nil + } + } + return nil, fmt.Errorf("user not found") +} diff --git a/integration-tests/smoke/ccip/ccip_rmn_test.go b/integration-tests/smoke/ccip/ccip_rmn_test.go index 4083be1c6be..6cd6bd9d63f 100644 --- a/integration-tests/smoke/ccip/ccip_rmn_test.go +++ b/integration-tests/smoke/ccip/ccip_rmn_test.go @@ -1,9 +1,14 @@ package smoke import ( + "context" + "encoding/binary" + "errors" "math/big" "os" + "slices" "strconv" + "strings" "testing" "time" @@ -13,8 +18,11 @@ import ( "github.com/rs/zerolog" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-ccip/pkg/reader" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + "github.com/smartcontractkit/chainlink/deployment/environment/devenv" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" @@ -75,7 +83,7 @@ func TestRMN_MultipleMessagesOnOneLaneNoWaitForExec(t *testing.T) { func TestRMN_NotEnoughObservers(t *testing.T) { runRmnTestCase(t, rmnTestCase{ name: "one message but not enough observers, should not get a commit report", - passIfNoCommitAfter: time.Minute, // wait for a minute and assert that commit report was not delivered + passIfNoCommitAfter: 15 * time.Second, homeChainConfig: homeChainConfig{ f: map[int]int{chain0: 1, chain1: 1}, }, @@ -121,7 +129,7 @@ func TestRMN_DifferentSigners(t *testing.T) { func TestRMN_NotEnoughSigners(t *testing.T) { runRmnTestCase(t, rmnTestCase{ name: "different signers and different observers", - passIfNoCommitAfter: time.Minute, // wait for a minute and assert that commit report was not delivered + passIfNoCommitAfter: 15 * time.Second, homeChainConfig: homeChainConfig{ f: map[int]int{chain0: 1, chain1: 1}, }, @@ -169,70 +177,77 @@ func TestRMN_DifferentRmnNodesForDifferentChains(t *testing.T) { }) } +func TestRMN_TwoMessagesOneSourceChainCursed(t *testing.T) { + runRmnTestCase(t, rmnTestCase{ + name: "two messages, one source chain is cursed", + passIfNoCommitAfter: 15 * time.Second, + cursedSubjectsPerChain: map[int][]int{ + chain1: {chain0}, + }, + homeChainConfig: homeChainConfig{ + f: map[int]int{chain0: 1, chain1: 1}, + }, + remoteChainsConfig: []remoteChainConfig{ + {chainIdx: chain0, f: 1}, + {chainIdx: chain1, f: 1}, + }, + rmnNodes: []rmnNode{ + {id: 0, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, + {id: 1, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, + {id: 2, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, + }, + messagesToSend: []messageToSend{ + {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, // <----- this message should not be committed + {fromChainIdx: chain1, toChainIdx: chain0, count: 1}, + }, + }) +} + +func TestRMN_GlobalCurseTwoMessagesOnTwoLanes(t *testing.T) { + runRmnTestCase(t, rmnTestCase{ + name: "global curse messages on two lanes", + waitForExec: false, + homeChainConfig: homeChainConfig{ + f: map[int]int{chain0: 1, chain1: 1}, + }, + remoteChainsConfig: []remoteChainConfig{ + {chainIdx: chain0, f: 1}, + {chainIdx: chain1, f: 1}, + }, + rmnNodes: []rmnNode{ + {id: 0, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, + {id: 1, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, + {id: 2, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, + }, + messagesToSend: []messageToSend{ + {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, + {fromChainIdx: chain1, toChainIdx: chain0, count: 5}, + }, + cursedSubjectsPerChain: map[int][]int{ + chain1: {globalCurse}, + chain0: {globalCurse}, + }, + passIfNoCommitAfter: 15 * time.Second, + }) +} + const ( - chain0 = 0 - chain1 = 1 + chain0 = 0 + chain1 = 1 + globalCurse = 1000 ) func runRmnTestCase(t *testing.T, tc rmnTestCase) { require.NoError(t, os.Setenv("ENABLE_RMN", "true")) + require.NoError(t, tc.validate()) + ctx := testcontext.Get(t) t.Logf("Running RMN test case: %s", tc.name) envWithRMN, rmnCluster := testsetups.NewLocalDevEnvironmentWithRMN(t, logger.TestLogger(t), len(tc.rmnNodes)) t.Logf("envWithRmn: %#v", envWithRMN) - var chainSelectors []uint64 - for _, chain := range envWithRMN.Env.Chains { - chainSelectors = append(chainSelectors, chain.Selector) - } - require.Greater(t, len(chainSelectors), 1, "There should be at least two chains") - - remoteChainSelectors := make([]uint64, 0, len(envWithRMN.Env.Chains)-1) - for _, chain := range envWithRMN.Env.Chains { - remoteChainSelectors = append(remoteChainSelectors, chain.Selector) - } - require.Greater(t, len(remoteChainSelectors), 0, "There should be at least one remote chain") - - var ( - rmnHomeNodes []rmn_home.RMNHomeNode - rmnRemoteSigners []rmn_remote.RMNRemoteSigner - ) - - for _, rmnNodeInfo := range tc.rmnNodes { - rmn := rmnCluster.Nodes["rmn_"+strconv.Itoa(rmnNodeInfo.id)] - - var offchainPublicKey [32]byte - copy(offchainPublicKey[:], rmn.RMN.OffchainPublicKey) - - rmnHomeNodes = append(rmnHomeNodes, rmn_home.RMNHomeNode{ - PeerId: rmn.Proxy.PeerID, - OffchainPublicKey: offchainPublicKey, - }) - - if rmnNodeInfo.isSigner { - if rmnNodeInfo.id < 0 { - t.Fatalf("node id is negative: %d", rmnNodeInfo.id) - } - rmnRemoteSigners = append(rmnRemoteSigners, rmn_remote.RMNRemoteSigner{ - OnchainPublicKey: rmn.RMN.EVMOnchainPublicKey, - NodeIndex: uint64(rmnNodeInfo.id), - }) - } - } - - var rmnHomeSourceChains []rmn_home.RMNHomeSourceChain - for remoteChainIdx, remoteF := range tc.homeChainConfig.f { - if remoteF < 0 { - t.Fatalf("negative remote F: %d", remoteF) - } - // configure remote chain details on the home contract - rmnHomeSourceChains = append(rmnHomeSourceChains, rmn_home.RMNHomeSourceChain{ - ChainSelector: chainSelectors[remoteChainIdx], - F: uint64(remoteF), - ObserverNodesBitmap: createObserverNodesBitmap(chainSelectors[remoteChainIdx], tc.rmnNodes, chainSelectors), - }) - } + tc.populateFields(t, envWithRMN, rmnCluster) onChainState, err := changeset.LoadOnchainState(envWithRMN.Env) require.NoError(t, err) @@ -244,22 +259,14 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { homeChainState, ok := onChainState.Chains[envWithRMN.HomeChainSel] require.True(t, ok) - allDigests, err := homeChainState.RMNHome.GetConfigDigests(&bind.CallOpts{ - Context: testcontext.Get(t), - }) + allDigests, err := homeChainState.RMNHome.GetConfigDigests(&bind.CallOpts{Context: ctx}) require.NoError(t, err) t.Logf("RMNHome candidateDigest before setting new candidate: %x, activeDigest: %x", allDigests.CandidateConfigDigest[:], allDigests.ActiveConfigDigest[:]) - staticConfig := rmn_home.RMNHomeStaticConfig{ - Nodes: rmnHomeNodes, - OffchainConfig: []byte{}, - } - dynamicConfig := rmn_home.RMNHomeDynamicConfig{ - SourceChains: rmnHomeSourceChains, - OffchainConfig: []byte{}, - } + staticConfig := rmn_home.RMNHomeStaticConfig{Nodes: tc.pf.rmnHomeNodes, OffchainConfig: []byte{}} + dynamicConfig := rmn_home.RMNHomeDynamicConfig{SourceChains: tc.pf.rmnHomeSourceChains, OffchainConfig: []byte{}} t.Logf("Setting RMNHome candidate with staticConfig: %+v, dynamicConfig: %+v, current candidateDigest: %x", staticConfig, dynamicConfig, allDigests.CandidateConfigDigest[:]) tx, err := homeChainState.RMNHome.SetCandidate(homeChain.DeployerKey, staticConfig, dynamicConfig, allDigests.CandidateConfigDigest) @@ -268,9 +275,7 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { _, err = deployment.ConfirmIfNoError(homeChain, tx, err) require.NoError(t, err) - candidateDigest, err := homeChainState.RMNHome.GetCandidateDigest(&bind.CallOpts{ - Context: testcontext.Get(t), - }) + candidateDigest, err := homeChainState.RMNHome.GetCandidateDigest(&bind.CallOpts{Context: ctx}) require.NoError(t, err) t.Logf("RMNHome candidateDigest after setting new candidate: %x", candidateDigest[:]) @@ -284,105 +289,70 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { require.NoError(t, err) // check the active digest is the same as the candidate digest - activeDigest, err := homeChainState.RMNHome.GetActiveDigest(&bind.CallOpts{ - Context: testcontext.Get(t), - }) + activeDigest, err := homeChainState.RMNHome.GetActiveDigest(&bind.CallOpts{Context: ctx}) require.NoError(t, err) require.Equalf(t, candidateDigest, activeDigest, "active digest should be the same as the previously candidate digest after promotion, previous candidate: %x, active: %x", candidateDigest[:], activeDigest[:]) - // Set RMN remote config appropriately - for _, remoteCfg := range tc.remoteChainsConfig { - remoteSel := chainSelectors[remoteCfg.chainIdx] - chState, ok := onChainState.Chains[remoteSel] - require.True(t, ok) - if remoteCfg.f < 0 { - t.Fatalf("negative F: %d", remoteCfg.f) - } - rmnRemoteConfig := rmn_remote.RMNRemoteConfig{ - RmnHomeContractConfigDigest: activeDigest, - Signers: rmnRemoteSigners, - F: uint64(remoteCfg.f), - } + tc.setRmnRemoteConfig(ctx, t, onChainState, activeDigest, envWithRMN) - chain := envWithRMN.Env.Chains[chainSelectors[remoteCfg.chainIdx]] - - t.Logf("Setting RMNRemote config with RMNHome active digest: %x, cfg: %+v", activeDigest[:], rmnRemoteConfig) - tx2, err2 := chState.RMNRemote.SetConfig(chain.DeployerKey, rmnRemoteConfig) - require.NoError(t, err2) - _, err2 = deployment.ConfirmIfNoError(chain, tx2, err2) - require.NoError(t, err2) + tc.killMarkedRmnNodes(t, rmnCluster) - // confirm the config is set correctly - config, err2 := chState.RMNRemote.GetVersionedConfig(&bind.CallOpts{ - Context: testcontext.Get(t), - }) - require.NoError(t, err2) - require.Equalf(t, - activeDigest, - config.Config.RmnHomeContractConfigDigest, - "RMNRemote config digest should be the same as the active digest of RMNHome after setting, RMNHome active: %x, RMNRemote config: %x", - activeDigest[:], config.Config.RmnHomeContractConfigDigest[:]) + changeset.ReplayLogs(t, envWithRMN.Env.Offchain, envWithRMN.ReplayBlocks) + require.NoError(t, changeset.AddLanesForAll(envWithRMN.Env, onChainState)) + disabledNodes := tc.disableOraclesIfThisIsACursingTestCase(ctx, t, envWithRMN) - t.Logf("RMNRemote config digest after setting: %x", config.Config.RmnHomeContractConfigDigest[:]) - } + startBlocks, seqNumCommit, seqNumExec := tc.sendMessages(t, onChainState, envWithRMN) + t.Logf("Sent all messages, seqNumCommit: %v seqNumExec: %v", seqNumCommit, seqNumExec) - // Kill the RMN nodes that are marked for force exit - for _, n := range tc.rmnNodes { - if n.forceExit { - t.Logf("Pausing RMN node %d", n.id) - rmnN := rmnCluster.Nodes["rmn_"+strconv.Itoa(n.id)] - require.NoError(t, osutil.ExecCmd(zerolog.Nop(), "docker kill "+rmnN.Proxy.ContainerName)) - t.Logf("Paused RMN node %d", n.id) - } - } + tc.callContractsToCurseChains(ctx, t, onChainState, envWithRMN) - changeset.ReplayLogs(t, envWithRMN.Env.Offchain, envWithRMN.ReplayBlocks) - // Add all lanes - require.NoError(t, changeset.AddLanesForAll(envWithRMN.Env, onChainState)) + tc.enableOracles(ctx, t, envWithRMN, disabledNodes) - // Need to keep track of the block number for each chain so that event subscription can be done from that block. - startBlocks := make(map[uint64]*uint64) expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) - for _, msg := range tc.messagesToSend { - fromChain := chainSelectors[msg.fromChainIdx] - toChain := chainSelectors[msg.toChainIdx] + for k, v := range seqNumCommit { + cursedSubjectsOfDest, exists := tc.pf.cursedSubjectsPerChainSel[k.DestChainSelector] + shouldSkip := exists && (slices.Contains(cursedSubjectsOfDest, globalCurse) || + slices.Contains(cursedSubjectsOfDest, k.SourceChainSelector)) - for i := 0; i < msg.count; i++ { - msgSentEvent := changeset.TestSendRequest(t, envWithRMN.Env, onChainState, fromChain, toChain, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(onChainState.Chains[toChain].Receiver.Address().Bytes(), 32), - Data: []byte("hello world"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - expectedSeqNum[changeset.SourceDestPair{ - SourceChainSelector: fromChain, - DestChainSelector: toChain, - }] = msgSentEvent.SequenceNumber - expectedSeqNumExec[changeset.SourceDestPair{ - SourceChainSelector: fromChain, - DestChainSelector: toChain, - }] = []uint64{msgSentEvent.SequenceNumber} - t.Logf("Sent message from chain %d to chain %d with seqNum %d", fromChain, toChain, msgSentEvent.SequenceNumber) + if !shouldSkip { + expectedSeqNum[k] = v } + } - zero := uint64(0) - startBlocks[toChain] = &zero + t.Logf("expectedSeqNums: %v", expectedSeqNum) + t.Logf("expectedSeqNums including cursed chains: %v", seqNumCommit) + + if len(tc.cursedSubjectsPerChain) > 0 && len(seqNumCommit) == len(expectedSeqNum) { + t.Fatalf("test case is wrong: no message was sent to non-cursed chains when you " + + "define curse subjects, your test case should have at least one message not expected to be delivered") } - t.Logf("Sent all messages, expectedSeqNum: %v", expectedSeqNum) commitReportReceived := make(chan struct{}) go func() { - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, envWithRMN.Env, onChainState, expectedSeqNum, startBlocks) - commitReportReceived <- struct{}{} + if len(expectedSeqNum) > 0 { + changeset.ConfirmCommitForAllWithExpectedSeqNums(t, envWithRMN.Env, onChainState, expectedSeqNum, startBlocks) + commitReportReceived <- struct{}{} + } + + if len(seqNumCommit) > 0 && len(seqNumCommit) > len(expectedSeqNum) { + // wait for a duration and assert that commit reports were not delivered for cursed source chains + changeset.ConfirmCommitForAllWithExpectedSeqNums(t, envWithRMN.Env, onChainState, seqNumCommit, startBlocks) + commitReportReceived <- struct{}{} + } }() if tc.passIfNoCommitAfter > 0 { // wait for a duration and assert that commit reports were not delivered + if len(expectedSeqNum) > 0 && len(seqNumCommit) > len(expectedSeqNum) { + t.Logf("⌛ Waiting for commit reports of non-cursed chains...") + <-commitReportReceived + t.Logf("✅ Commit reports of non-cursed chains received") + } + tim := time.NewTimer(tc.passIfNoCommitAfter) t.Logf("waiting for %s before asserting that commit report was not received", tc.passIfNoCommitAfter) + select { case <-commitReportReceived: t.Errorf("Commit report was received while it was not expected") @@ -398,7 +368,7 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { if tc.waitForExec { t.Logf("⌛ Waiting for exec reports...") - changeset.ConfirmExecWithSeqNrsForAll(t, envWithRMN.Env, onChainState, expectedSeqNumExec, startBlocks) + changeset.ConfirmExecWithSeqNrsForAll(t, envWithRMN.Env, onChainState, seqNumExec, startBlocks) t.Logf("✅ Exec report") } } @@ -447,10 +417,236 @@ type rmnTestCase struct { name string // If set to 0, the test will wait for commit reports. // If set to a positive value, the test will wait for that duration and will assert that commit report was not delivered. - passIfNoCommitAfter time.Duration - waitForExec bool - homeChainConfig homeChainConfig - remoteChainsConfig []remoteChainConfig - rmnNodes []rmnNode - messagesToSend []messageToSend + passIfNoCommitAfter time.Duration + cursedSubjectsPerChain map[int][]int + waitForExec bool + homeChainConfig homeChainConfig + remoteChainsConfig []remoteChainConfig + rmnNodes []rmnNode + messagesToSend []messageToSend + + // populated fields after environment setup + pf testCasePopulatedFields +} + +type testCasePopulatedFields struct { + chainSelectors []uint64 + rmnHomeNodes []rmn_home.RMNHomeNode + rmnRemoteSigners []rmn_remote.RMNRemoteSigner + rmnHomeSourceChains []rmn_home.RMNHomeSourceChain + cursedSubjectsPerChainSel map[uint64][]uint64 +} + +func (tc *rmnTestCase) populateFields(t *testing.T, envWithRMN changeset.DeployedEnv, rmnCluster devenv.RMNCluster) { + require.GreaterOrEqual(t, len(envWithRMN.Env.Chains), 2, "test assumes at least two chains") + for _, chain := range envWithRMN.Env.Chains { + tc.pf.chainSelectors = append(tc.pf.chainSelectors, chain.Selector) + } + + for _, rmnNodeInfo := range tc.rmnNodes { + rmn := rmnCluster.Nodes["rmn_"+strconv.Itoa(rmnNodeInfo.id)] + + var offchainPublicKey [32]byte + copy(offchainPublicKey[:], rmn.RMN.OffchainPublicKey) + + tc.pf.rmnHomeNodes = append(tc.pf.rmnHomeNodes, rmn_home.RMNHomeNode{ + PeerId: rmn.Proxy.PeerID, + OffchainPublicKey: offchainPublicKey, + }) + + if rmnNodeInfo.isSigner { + if rmnNodeInfo.id < 0 { + t.Fatalf("node id is negative: %d", rmnNodeInfo.id) + } + tc.pf.rmnRemoteSigners = append(tc.pf.rmnRemoteSigners, rmn_remote.RMNRemoteSigner{ + OnchainPublicKey: rmn.RMN.EVMOnchainPublicKey, + NodeIndex: uint64(rmnNodeInfo.id), + }) + } + } + + for remoteChainIdx, remoteF := range tc.homeChainConfig.f { + if remoteF < 0 { + t.Fatalf("negative remote F: %d", remoteF) + } + // configure remote chain details on the home contract + tc.pf.rmnHomeSourceChains = append(tc.pf.rmnHomeSourceChains, rmn_home.RMNHomeSourceChain{ + ChainSelector: tc.pf.chainSelectors[remoteChainIdx], + F: uint64(remoteF), + ObserverNodesBitmap: createObserverNodesBitmap(tc.pf.chainSelectors[remoteChainIdx], tc.rmnNodes, tc.pf.chainSelectors), + }) + } + + // populate cursed subjects with actual chain selectors + tc.pf.cursedSubjectsPerChainSel = make(map[uint64][]uint64) + for chainIdx, subjects := range tc.cursedSubjectsPerChain { + chainSel := tc.pf.chainSelectors[chainIdx] + for _, subject := range subjects { + subjSel := uint64(globalCurse) + if subject != globalCurse { + subjSel = tc.pf.chainSelectors[subject] + } + tc.pf.cursedSubjectsPerChainSel[chainSel] = append(tc.pf.cursedSubjectsPerChainSel[chainSel], subjSel) + } + } +} + +func (tc rmnTestCase) validate() error { + if len(tc.cursedSubjectsPerChain) > 0 && tc.passIfNoCommitAfter == 0 { + return errors.New("when you define cursed subjects you also need to define the duration that the " + + "test will wait for non-transmitted roots") + } + return nil +} + +func (tc rmnTestCase) setRmnRemoteConfig( + ctx context.Context, + t *testing.T, + onChainState changeset.CCIPOnChainState, + activeDigest [32]byte, + envWithRMN changeset.DeployedEnv) { + for _, remoteCfg := range tc.remoteChainsConfig { + remoteSel := tc.pf.chainSelectors[remoteCfg.chainIdx] + chState, ok := onChainState.Chains[remoteSel] + require.True(t, ok) + if remoteCfg.f < 0 { + t.Fatalf("negative F: %d", remoteCfg.f) + } + rmnRemoteConfig := rmn_remote.RMNRemoteConfig{ + RmnHomeContractConfigDigest: activeDigest, + Signers: tc.pf.rmnRemoteSigners, + F: uint64(remoteCfg.f), + } + + chain := envWithRMN.Env.Chains[tc.pf.chainSelectors[remoteCfg.chainIdx]] + + t.Logf("Setting RMNRemote config with RMNHome active digest: %x, cfg: %+v", activeDigest[:], rmnRemoteConfig) + tx2, err2 := chState.RMNRemote.SetConfig(chain.DeployerKey, rmnRemoteConfig) + require.NoError(t, err2) + _, err2 = deployment.ConfirmIfNoError(chain, tx2, err2) + require.NoError(t, err2) + + // confirm the config is set correctly + config, err2 := chState.RMNRemote.GetVersionedConfig(&bind.CallOpts{Context: ctx}) + require.NoError(t, err2) + require.Equalf(t, + activeDigest, + config.Config.RmnHomeContractConfigDigest, + "RMNRemote config digest should be the same as the active digest of RMNHome after setting, RMNHome active: %x, RMNRemote config: %x", + activeDigest[:], config.Config.RmnHomeContractConfigDigest[:]) + + t.Logf("RMNRemote config digest after setting: %x", config.Config.RmnHomeContractConfigDigest[:]) + } +} + +func (tc rmnTestCase) killMarkedRmnNodes(t *testing.T, rmnCluster devenv.RMNCluster) { + for _, n := range tc.rmnNodes { + if n.forceExit { + t.Logf("Pausing RMN node %d", n.id) + rmnN := rmnCluster.Nodes["rmn_"+strconv.Itoa(n.id)] + require.NoError(t, osutil.ExecCmd(zerolog.Nop(), "docker kill "+rmnN.Proxy.ContainerName)) + t.Logf("Paused RMN node %d", n.id) + } + } +} + +func (tc rmnTestCase) disableOraclesIfThisIsACursingTestCase(ctx context.Context, t *testing.T, envWithRMN changeset.DeployedEnv) []string { + disabledNodes := make([]string, 0) + + if len(tc.cursedSubjectsPerChain) > 0 { + listNodesResp, err := envWithRMN.Env.Offchain.ListNodes(ctx, &node.ListNodesRequest{}) + require.NoError(t, err) + + for _, n := range listNodesResp.Nodes { + if strings.HasPrefix(n.Name, "bootstrap") { + continue + } + _, err := envWithRMN.Env.Offchain.DisableNode(ctx, &node.DisableNodeRequest{Id: n.Id}) + require.NoError(t, err) + disabledNodes = append(disabledNodes, n.Id) + t.Logf("node %s disabled", n.Id) + } + } + + return disabledNodes +} + +func (tc rmnTestCase) sendMessages(t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN changeset.DeployedEnv) (map[uint64]*uint64, map[changeset.SourceDestPair]uint64, map[changeset.SourceDestPair][]uint64) { + startBlocks := make(map[uint64]*uint64) + seqNumCommit := make(map[changeset.SourceDestPair]uint64) + seqNumExec := make(map[changeset.SourceDestPair][]uint64) + + for _, msg := range tc.messagesToSend { + fromChain := tc.pf.chainSelectors[msg.fromChainIdx] + toChain := tc.pf.chainSelectors[msg.toChainIdx] + + for i := 0; i < msg.count; i++ { + msgSentEvent := changeset.TestSendRequest(t, envWithRMN.Env, onChainState, fromChain, toChain, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(onChainState.Chains[toChain].Receiver.Address().Bytes(), 32), + Data: []byte("hello world"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + seqNumCommit[changeset.SourceDestPair{ + SourceChainSelector: fromChain, + DestChainSelector: toChain, + }] = msgSentEvent.SequenceNumber + seqNumExec[changeset.SourceDestPair{ + SourceChainSelector: fromChain, + DestChainSelector: toChain, + }] = []uint64{msgSentEvent.SequenceNumber} + t.Logf("Sent message from chain %d to chain %d with seqNum %d", fromChain, toChain, msgSentEvent.SequenceNumber) + } + + zero := uint64(0) + startBlocks[toChain] = &zero + } + + return startBlocks, seqNumCommit, seqNumExec +} + +func (tc rmnTestCase) callContractsToCurseChains(ctx context.Context, t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN changeset.DeployedEnv) { + for _, remoteCfg := range tc.remoteChainsConfig { + remoteSel := tc.pf.chainSelectors[remoteCfg.chainIdx] + chState, ok := onChainState.Chains[remoteSel] + require.True(t, ok) + chain, ok := envWithRMN.Env.Chains[remoteSel] + require.True(t, ok) + + cursedSubjects, ok := tc.cursedSubjectsPerChain[remoteCfg.chainIdx] + if !ok { + continue // nothing to curse on this chain + } + + for _, subjectDescription := range cursedSubjects { + subj := reader.GlobalCurseSubject + if subjectDescription != globalCurse { + subj = chainSelectorToBytes16(tc.pf.chainSelectors[subjectDescription]) + } + t.Logf("cursing subject %d (%d)", subj, subjectDescription) + txCurse, errCurse := chState.RMNRemote.Curse(chain.DeployerKey, subj) + _, errConfirm := deployment.ConfirmIfNoError(chain, txCurse, errCurse) + require.NoError(t, errConfirm) + } + + cs, err := chState.RMNRemote.GetCursedSubjects(&bind.CallOpts{Context: ctx}) + require.NoError(t, err) + t.Logf("Cursed subjects: %v", cs) + } +} + +func (tc rmnTestCase) enableOracles(ctx context.Context, t *testing.T, envWithRMN changeset.DeployedEnv, nodeIDs []string) { + for _, n := range nodeIDs { + _, err := envWithRMN.Env.Offchain.EnableNode(ctx, &node.EnableNodeRequest{Id: n}) + require.NoError(t, err) + t.Logf("node %s enabled", n) + } +} + +func chainSelectorToBytes16(chainSel uint64) [16]byte { + var result [16]byte + // Convert the uint64 to bytes and place it in the last 8 bytes of the array + binary.BigEndian.PutUint64(result[8:], chainSel) + return result } diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go index d2adbaaa484..ca30c9281c4 100644 --- a/integration-tests/smoke/ccip/ccip_test.go +++ b/integration-tests/smoke/ccip/ccip_test.go @@ -1,7 +1,6 @@ package smoke import ( - "math/big" "testing" "github.com/ethereum/go-ethereum/common" @@ -11,7 +10,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -19,7 +17,8 @@ import ( func TestInitialDeployOnLocal(t *testing.T) { t.Parallel() lggr := logger.TestLogger(t) - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, nil) + config := &changeset.TestConfigs{} + tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) e := tenv.Env state, err := changeset.LoadOnchainState(e) require.NoError(t, err) @@ -40,142 +39,20 @@ func TestInitialDeployOnLocal(t *testing.T) { require.NoError(t, err) block := latesthdr.Number.Uint64() startBlocks[dest] = &block - msgSentEvent := changeset.TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), - Data: []byte("hello world"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - expectedSeqNum[changeset.SourceDestPair{ - SourceChainSelector: src, - DestChainSelector: dest, - }] = msgSentEvent.SequenceNumber - expectedSeqNumExec[changeset.SourceDestPair{ - SourceChainSelector: src, - DestChainSelector: dest, - }] = []uint64{msgSentEvent.SequenceNumber} - } - } - - // Wait for all commit reports to land. - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) - - // After commit is reported on all chains, token prices should be updated in FeeQuoter. - for dest := range e.Chains { - linkAddress := state.Chains[dest].LinkToken.Address() - feeQuoter := state.Chains[dest].FeeQuoter - timestampedPrice, err := feeQuoter.GetTokenPrice(nil, linkAddress) - require.NoError(t, err) - require.Equal(t, changeset.MockLinkPrice, timestampedPrice.Value) - } - - // Wait for all exec reports to land - changeset.ConfirmExecWithSeqNrsForAll(t, e, state, expectedSeqNumExec, startBlocks) - - // TODO: Apply the proposal. -} - -func TestTokenTransfer(t *testing.T) { - t.Parallel() - lggr := logger.TestLogger(t) - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, nil) - e := tenv.Env - state, err := changeset.LoadOnchainState(e) - require.NoError(t, err) - - srcToken, _, dstToken, _, err := changeset.DeployTransferableToken( - lggr, - tenv.Env.Chains, - tenv.HomeChainSel, - tenv.FeedChainSel, - state, - e.ExistingAddresses, - "MY_TOKEN", - ) - require.NoError(t, err) - - // Add all lanes - require.NoError(t, changeset.AddLanesForAll(e, state)) - // Need to keep track of the block number for each chain so that event subscription can be done from that block. - startBlocks := make(map[uint64]*uint64) - // Send a message from each chain to every other chain. - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) - - twoCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2)) - tx, err := srcToken.Mint( - e.Chains[tenv.HomeChainSel].DeployerKey, - e.Chains[tenv.HomeChainSel].DeployerKey.From, - new(big.Int).Mul(twoCoins, big.NewInt(10)), - ) - require.NoError(t, err) - _, err = e.Chains[tenv.HomeChainSel].Confirm(tx) - require.NoError(t, err) - - tx, err = dstToken.Mint( - e.Chains[tenv.FeedChainSel].DeployerKey, - e.Chains[tenv.FeedChainSel].DeployerKey.From, - new(big.Int).Mul(twoCoins, big.NewInt(10)), - ) - require.NoError(t, err) - _, err = e.Chains[tenv.FeedChainSel].Confirm(tx) - require.NoError(t, err) - - tx, err = srcToken.Approve(e.Chains[tenv.HomeChainSel].DeployerKey, state.Chains[tenv.HomeChainSel].Router.Address(), twoCoins) - require.NoError(t, err) - _, err = e.Chains[tenv.HomeChainSel].Confirm(tx) - require.NoError(t, err) - tx, err = dstToken.Approve(e.Chains[tenv.FeedChainSel].DeployerKey, state.Chains[tenv.FeedChainSel].Router.Address(), twoCoins) - require.NoError(t, err) - _, err = e.Chains[tenv.FeedChainSel].Confirm(tx) - require.NoError(t, err) - - tokens := map[uint64][]router.ClientEVMTokenAmount{ - tenv.HomeChainSel: {{ - Token: srcToken.Address(), - Amount: twoCoins, - }}, - tenv.FeedChainSel: {{ - Token: dstToken.Address(), - Amount: twoCoins, - }}, - } - - for src := range e.Chains { - for dest, destChain := range e.Chains { - if src == dest { - continue - } - latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[dest] = &block - - var ( - receiver = common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32) - data = []byte("hello world") - feeToken = common.HexToAddress("0x0") - msgSentEvent *onramp.OnRampCCIPMessageSent - ) - if src == tenv.HomeChainSel && dest == tenv.FeedChainSel { - msgSentEvent = changeset.TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ - Receiver: receiver, - Data: data, - TokenAmounts: tokens[src], - FeeToken: feeToken, - ExtraArgs: nil, - }) - } else { - msgSentEvent = changeset.TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ - Receiver: receiver, - Data: data, + require.GreaterOrEqual(t, len(tenv.Users[src]), 2) + msgSentEvent, err := changeset.DoSendRequest(t, e, state, + changeset.WithSender(tenv.Users[src][1]), + changeset.WithSourceChain(src), + changeset.WithDestChain(dest), + changeset.WithTestRouter(false), + changeset.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello world"), TokenAmounts: nil, - FeeToken: feeToken, + FeeToken: common.HexToAddress("0x0"), ExtraArgs: nil, - }) - } - + })) + require.NoError(t, err) expectedSeqNum[changeset.SourceDestPair{ SourceChainSelector: src, DestChainSelector: dest, @@ -202,7 +79,5 @@ func TestTokenTransfer(t *testing.T) { // Wait for all exec reports to land changeset.ConfirmExecWithSeqNrsForAll(t, e, state, expectedSeqNumExec, startBlocks) - balance, err := dstToken.BalanceOf(nil, state.Chains[tenv.FeedChainSel].Receiver.Address()) - require.NoError(t, err) - require.Equal(t, twoCoins, balance) + // TODO: Apply the proposal. } diff --git a/integration-tests/smoke/ccip/ccip_token_price_updates_test.go b/integration-tests/smoke/ccip/ccip_token_price_updates_test.go new file mode 100644 index 00000000000..6a193397d7e --- /dev/null +++ b/integration-tests/smoke/ccip/ccip_token_price_updates_test.go @@ -0,0 +1,152 @@ +package smoke + +import ( + "context" + "math" + "math/big" + "strings" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func Test_CCIPTokenPriceUpdates(t *testing.T) { + lggr := logger.TestLogger(t) + ctx := changeset.Context(t) + callOpts := &bind.CallOpts{Context: ctx} + + var tokenPriceExpiry = 5 * time.Second + e, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, &changeset.TestConfigs{ + OCRConfigOverride: func(params changeset.CCIPOCRParams) changeset.CCIPOCRParams { + params.CommitOffChainConfig.TokenPriceBatchWriteFrequency = *config.MustNewDuration(tokenPriceExpiry) + return params + }, + }) + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + require.NoError(t, changeset.AddLanesForAll(e.Env, state)) + + allChainSelectors := maps.Keys(e.Env.Chains) + assert.GreaterOrEqual(t, len(allChainSelectors), 2, "test requires at least 2 chains") + + sourceChain1 := allChainSelectors[0] + + feeQuoter1 := state.Chains[sourceChain1].FeeQuoter + + feeTokensChain1, err := feeQuoter1.GetFeeTokens(callOpts) + require.NoError(t, err) + t.Logf("feeTokens: %v", feeTokensChain1) + + tokenPricesBefore, err := feeQuoter1.GetTokenPrices(callOpts, feeTokensChain1) + require.NoError(t, err) + t.Logf("tokenPrices: %v", tokenPricesBefore) + + // assert token prices updated due to time expiration + assert.Eventually(t, func() bool { + tokenPricesNow, err := feeQuoter1.GetTokenPrices(callOpts, feeTokensChain1) + require.NoError(t, err) + t.Logf("tokenPrices: %v", tokenPricesNow) + + // both tokens should have same price but different timestamp since there was an update due to time deviation + for i, price := range tokenPricesNow { + if tokenPricesBefore[i].Timestamp == price.Timestamp { + tokenPricesBefore = tokenPricesNow + return false // timestamp is the same + } + if tokenPricesBefore[i].Value.Cmp(price.Value) != 0 { + tokenPricesBefore = tokenPricesNow + return false // price was updated + } + } + t.Log("time expiration assertions complete") + return true + }, tests.WaitTimeout(t), 500*time.Millisecond) + + // disable oracles to prevent price updates while we manually edit token prices + disabledOracleIDs := disableOracles(ctx, t, e.Env.Offchain) + + assert.Eventually(t, func() bool { + // manually update token prices by setting values to maxUint64 and 0 + tx, err := feeQuoter1.UpdatePrices(e.Env.Chains[sourceChain1].DeployerKey, fee_quoter.InternalPriceUpdates{ + TokenPriceUpdates: []fee_quoter.InternalTokenPriceUpdate{ + {SourceToken: feeTokensChain1[0], UsdPerToken: big.NewInt(0).SetUint64(math.MaxUint64)}, + {SourceToken: feeTokensChain1[1], UsdPerToken: big.NewInt(0)}, + }, + }) + require.NoError(t, err) + + _, err = deployment.ConfirmIfNoError(e.Env.Chains[sourceChain1], tx, err) + require.NoError(t, err) + t.Logf("manually editing token prices") + + tokenPricesNow, err := feeQuoter1.GetTokenPrices(callOpts, feeTokensChain1) + require.NoError(t, err) + t.Logf("tokenPrices straight after: %v", tokenPricesNow) + + if uint64(math.MaxUint64) != tokenPricesNow[0].Value.Uint64() { + return false + } + if uint64(0) != tokenPricesNow[1].Value.Uint64() { + return false + } + return true + + // retry because there might've been a commit report inflight + }, tests.WaitTimeout(t), 200*time.Millisecond) + + enableOracles(ctx, t, e.Env.Offchain, disabledOracleIDs) + + // wait until price goes back to the original + assert.Eventually(t, func() bool { + tokenPricesNow, err := feeQuoter1.GetTokenPrices(callOpts, feeTokensChain1) + require.NoError(t, err) + t.Logf("tokenPrices: %v tokenPricesBefore: %v", tokenPricesNow, tokenPricesBefore) + + if tokenPricesNow[0].Value.Cmp(tokenPricesBefore[0].Value) != 0 { + return false + } + if tokenPricesNow[1].Value.Cmp(tokenPricesBefore[1].Value) != 0 { + return false + } + return true + }, tests.WaitTimeout(t), 500*time.Millisecond) +} + +func disableOracles(ctx context.Context, t *testing.T, client deployment.OffchainClient) []string { + var disabledOracleIDs []string + listNodesResp, err := client.ListNodes(ctx, &node.ListNodesRequest{}) + require.NoError(t, err) + + for _, n := range listNodesResp.Nodes { + if strings.HasPrefix(n.Name, "bootstrap") { + continue + } + _, err := client.DisableNode(ctx, &node.DisableNodeRequest{Id: n.Id}) + require.NoError(t, err) + disabledOracleIDs = append(disabledOracleIDs, n.Id) + t.Logf("node %s disabled", n.Id) + } + + return disabledOracleIDs +} + +func enableOracles(ctx context.Context, t *testing.T, client deployment.OffchainClient, oracleIDs []string) { + for _, n := range oracleIDs { + _, err := client.EnableNode(ctx, &node.EnableNodeRequest{Id: n}) + require.NoError(t, err) + t.Logf("node %s enabled", n) + } +} diff --git a/integration-tests/smoke/ccip/ccip_token_transfer_test.go b/integration-tests/smoke/ccip/ccip_token_transfer_test.go new file mode 100644 index 00000000000..13abe33fe7c --- /dev/null +++ b/integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -0,0 +1,223 @@ +package smoke + +import ( + "math/big" + "testing" + + "golang.org/x/exp/maps" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestTokenTransfer(t *testing.T) { + lggr := logger.TestLogger(t) + ctx := tests.Context(t) + config := &changeset.TestConfigs{} + + tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + NumOfUsersPerChain: 3, + }, config) + + e := tenv.Env + state, err := changeset.LoadOnchainState(e) + require.NoError(t, err) + require.GreaterOrEqual(t, len(e.Chains), 2) + + allChainSelectors := maps.Keys(e.Chains) + sourceChain, destChain := allChainSelectors[0], allChainSelectors[1] + ownerSourceChain := e.Chains[sourceChain].DeployerKey + ownerDestChain := e.Chains[destChain].DeployerKey + + require.GreaterOrEqual(t, len(tenv.Users[sourceChain]), 2) + require.GreaterOrEqual(t, len(tenv.Users[destChain]), 2) + selfServeSrcTokenPoolDeployer := tenv.Users[sourceChain][1] + selfServeDestTokenPoolDeployer := tenv.Users[destChain][1] + + oneE18 := new(big.Int).SetUint64(1e18) + + // Deploy tokens and pool by CCIP Owner + srcToken, _, destToken, _, err := changeset.DeployTransferableToken( + lggr, + tenv.Env.Chains, + sourceChain, + destChain, + ownerSourceChain, + ownerDestChain, + state, + e.ExistingAddresses, + "OWNER_TOKEN", + ) + require.NoError(t, err) + + // Deploy Self Serve tokens and pool + selfServeSrcToken, _, selfServeDestToken, _, err := changeset.DeployTransferableToken( + lggr, + tenv.Env.Chains, + sourceChain, + destChain, + selfServeSrcTokenPoolDeployer, + selfServeDestTokenPoolDeployer, + state, + e.ExistingAddresses, + "SELF_SERVE_TOKEN", + ) + require.NoError(t, err) + require.NoError(t, changeset.AddLanesForAll(e, state)) + + changeset.MintAndAllow( + t, + e, + state, + map[uint64][]changeset.MintTokenInfo{ + sourceChain: { + changeset.NewMintTokenInfo(selfServeSrcTokenPoolDeployer, selfServeSrcToken), + changeset.NewMintTokenInfo(ownerSourceChain, srcToken), + }, + destChain: { + changeset.NewMintTokenInfo(selfServeDestTokenPoolDeployer, selfServeDestToken), + changeset.NewMintTokenInfo(ownerDestChain, destToken), + }, + }, + ) + + tcs := []changeset.TestTransferRequest{ + { + Name: "Send token to EOA", + SourceChain: sourceChain, + DestChain: destChain, + Tokens: []router.ClientEVMTokenAmount{ + { + Token: srcToken.Address(), + Amount: oneE18, + }, + }, + Receiver: utils.RandomAddress(), + ExpectedTokenBalances: map[common.Address]*big.Int{ + destToken.Address(): oneE18, + }, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + }, + { + Name: "Send token to contract", + SourceChain: sourceChain, + DestChain: destChain, + Tokens: []router.ClientEVMTokenAmount{ + { + Token: srcToken.Address(), + Amount: oneE18, + }, + }, + Receiver: state.Chains[destChain].Receiver.Address(), + ExpectedTokenBalances: map[common.Address]*big.Int{ + destToken.Address(): oneE18, + }, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + }, + { + Name: "Send N tokens to contract", + SourceChain: destChain, + DestChain: sourceChain, + Tokens: []router.ClientEVMTokenAmount{ + { + Token: selfServeDestToken.Address(), + Amount: oneE18, + }, + { + Token: destToken.Address(), + Amount: oneE18, + }, + { + Token: selfServeDestToken.Address(), + Amount: oneE18, + }, + }, + Receiver: state.Chains[sourceChain].Receiver.Address(), + ExtraArgs: changeset.MakeEVMExtraArgsV2(300_000, false), + ExpectedTokenBalances: map[common.Address]*big.Int{ + selfServeSrcToken.Address(): new(big.Int).Add(oneE18, oneE18), + srcToken.Address(): oneE18, + }, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + }, + { + Name: "Sending token transfer with custom gasLimits to the EOA is successful", + SourceChain: destChain, + DestChain: sourceChain, + Tokens: []router.ClientEVMTokenAmount{ + { + Token: selfServeDestToken.Address(), + Amount: oneE18, + }, + { + Token: destToken.Address(), + Amount: new(big.Int).Add(oneE18, oneE18), + }, + }, + Receiver: utils.RandomAddress(), + ExtraArgs: changeset.MakeEVMExtraArgsV2(1, false), + ExpectedTokenBalances: map[common.Address]*big.Int{ + selfServeSrcToken.Address(): oneE18, + srcToken.Address(): new(big.Int).Add(oneE18, oneE18), + }, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + }, + { + Name: "Sending PTT with too low gas limit leads to the revert when receiver is a contract", + SourceChain: destChain, + DestChain: sourceChain, + Tokens: []router.ClientEVMTokenAmount{ + { + Token: selfServeDestToken.Address(), + Amount: oneE18, + }, + { + Token: destToken.Address(), + Amount: oneE18, + }, + }, + Receiver: state.Chains[sourceChain].Receiver.Address(), + Data: []byte("this should be reverted because gasLimit is too low, no tokens are transferred as well"), + ExtraArgs: changeset.MakeEVMExtraArgsV2(1, false), + ExpectedTokenBalances: map[common.Address]*big.Int{ + selfServeSrcToken.Address(): big.NewInt(0), + srcToken.Address(): big.NewInt(0), + }, + ExpectedStatus: changeset.EXECUTION_STATE_FAILURE, + }, + } + + startBlocks, expectedSeqNums, expectedExecutionStates, expectedTokenBalances := + changeset.TransferMultiple(ctx, t, e, state, tcs) + + err = changeset.ConfirmMultipleCommits( + t, + e.Chains, + state.Chains, + startBlocks, + false, + expectedSeqNums, + ) + require.NoError(t, err) + + execStates := changeset.ConfirmExecWithSeqNrsForAll( + t, + e, + state, + changeset.SeqNumberRageToSlice(expectedSeqNums), + startBlocks, + ) + require.Equal(t, expectedExecutionStates, execStates) + + changeset.WaitForTokenBalances(ctx, t, e.Chains, expectedTokenBalances) +} diff --git a/integration-tests/smoke/ccip/ccip_usdc_test.go b/integration-tests/smoke/ccip/ccip_usdc_test.go index c50c2617094..2dae3f3c48e 100644 --- a/integration-tests/smoke/ccip/ccip_usdc_test.go +++ b/integration-tests/smoke/ccip/ccip_usdc_test.go @@ -3,22 +3,18 @@ package smoke import ( "math/big" "testing" - "time" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "golang.org/x/exp/maps" + "golang.org/x/sync/errgroup" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -34,11 +30,16 @@ import ( */ func TestUSDCTokenTransfer(t *testing.T) { lggr := logger.TestLogger(t) + ctx := tests.Context(t) config := &changeset.TestConfigs{ IsUSDC: true, } - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) - //tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 3, 4, config) + tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, memory.MemoryEnvironmentConfig{ + Chains: 3, + NumOfUsersPerChain: 3, + Nodes: 4, + Bootstraps: 1, + }, config) e := tenv.Env state, err := changeset.LoadOnchainState(e) @@ -49,6 +50,10 @@ func TestUSDCTokenTransfer(t *testing.T) { chainC := allChainSelectors[1] chainB := allChainSelectors[2] + ownerChainA := e.Chains[chainA].DeployerKey + ownerChainC := e.Chains[chainC].DeployerKey + ownerChainB := e.Chains[chainB].DeployerKey + aChainUSDC, cChainUSDC, err := changeset.ConfigureUSDCTokenPools(lggr, e.Chains, chainA, chainC, state) require.NoError(t, err) @@ -60,6 +65,8 @@ func TestUSDCTokenTransfer(t *testing.T) { tenv.Env.Chains, chainA, chainC, + ownerChainA, + ownerChainC, state, e.ExistingAddresses, "MY_TOKEN", @@ -69,55 +76,51 @@ func TestUSDCTokenTransfer(t *testing.T) { // Add all lanes require.NoError(t, changeset.AddLanesForAll(e, state)) - mintAndAllow(t, e, state, map[uint64][]*burn_mint_erc677.BurnMintERC677{ - chainA: {aChainUSDC, aChainToken}, - chainB: {bChainUSDC}, - chainC: {cChainUSDC, cChainToken}, - }) - - err = changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainA], state.Chains[chainA], chainC, aChainUSDC) - require.NoError(t, err) - - err = changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainB], state.Chains[chainB], chainC, bChainUSDC) - require.NoError(t, err) + changeset.MintAndAllow( + t, + e, + state, + map[uint64][]changeset.MintTokenInfo{ + chainA: { + changeset.NewMintTokenInfo(ownerChainA, aChainUSDC, aChainToken), + }, + chainB: { + changeset.NewMintTokenInfo(ownerChainB, bChainUSDC), + }, + chainC: { + changeset.NewMintTokenInfo(ownerChainC, cChainUSDC, cChainToken), + }, + }, + ) - err = changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainA, cChainUSDC) + err = updateFeeQuoters(lggr, e, state, chainA, chainB, chainC, aChainUSDC, bChainUSDC, cChainUSDC) require.NoError(t, err) // MockE2EUSDCTransmitter always mint 1, see MockE2EUSDCTransmitter.sol for more details tinyOneCoin := new(big.Int).SetUint64(1) - tcs := []struct { - name string - receiver common.Address - sourceChain uint64 - destChain uint64 - tokens []router.ClientEVMTokenAmount - data []byte - expectedTokenBalances map[common.Address]*big.Int - expectedExecutionState int - }{ + tcs := []changeset.TestTransferRequest{ { - name: "single USDC token transfer to EOA", - receiver: utils.RandomAddress(), - sourceChain: chainC, - destChain: chainA, - tokens: []router.ClientEVMTokenAmount{ + Name: "single USDC token transfer to EOA", + Receiver: utils.RandomAddress(), + SourceChain: chainC, + DestChain: chainA, + Tokens: []router.ClientEVMTokenAmount{ { Token: cChainUSDC.Address(), Amount: tinyOneCoin, }}, - expectedTokenBalances: map[common.Address]*big.Int{ + ExpectedTokenBalances: map[common.Address]*big.Int{ aChainUSDC.Address(): tinyOneCoin, }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, }, { - name: "multiple USDC tokens within the same message", - receiver: utils.RandomAddress(), - sourceChain: chainC, - destChain: chainA, - tokens: []router.ClientEVMTokenAmount{ + Name: "multiple USDC tokens within the same message", + Receiver: utils.RandomAddress(), + SourceChain: chainC, + DestChain: chainA, + Tokens: []router.ClientEVMTokenAmount{ { Token: cChainUSDC.Address(), Amount: tinyOneCoin, @@ -127,18 +130,18 @@ func TestUSDCTokenTransfer(t *testing.T) { Amount: tinyOneCoin, }, }, - expectedTokenBalances: map[common.Address]*big.Int{ - // 2 coins because of the same receiver + ExpectedTokenBalances: map[common.Address]*big.Int{ + // 2 coins because of the same Receiver aChainUSDC.Address(): new(big.Int).Add(tinyOneCoin, tinyOneCoin), }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, }, { - name: "USDC token together with another token transferred to EOA", - receiver: utils.RandomAddress(), - sourceChain: chainA, - destChain: chainC, - tokens: []router.ClientEVMTokenAmount{ + Name: "USDC token together with another token transferred to EOA", + Receiver: utils.RandomAddress(), + SourceChain: chainA, + DestChain: chainC, + Tokens: []router.ClientEVMTokenAmount{ { Token: aChainUSDC.Address(), Amount: tinyOneCoin, @@ -148,218 +151,111 @@ func TestUSDCTokenTransfer(t *testing.T) { Amount: new(big.Int).Mul(tinyOneCoin, big.NewInt(10)), }, }, - expectedTokenBalances: map[common.Address]*big.Int{ + ExpectedTokenBalances: map[common.Address]*big.Int{ cChainUSDC.Address(): tinyOneCoin, cChainToken.Address(): new(big.Int).Mul(tinyOneCoin, big.NewInt(10)), }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, }, { - name: "programmable token transfer to valid contract receiver", - receiver: state.Chains[chainC].Receiver.Address(), - sourceChain: chainA, - destChain: chainC, - tokens: []router.ClientEVMTokenAmount{ + Name: "USDC programmable token transfer to valid contract receiver", + Receiver: state.Chains[chainC].Receiver.Address(), + SourceChain: chainA, + DestChain: chainC, + Tokens: []router.ClientEVMTokenAmount{ { Token: aChainUSDC.Address(), Amount: tinyOneCoin, }, }, - data: []byte("hello world"), - expectedTokenBalances: map[common.Address]*big.Int{ + Data: []byte("hello world"), + ExpectedTokenBalances: map[common.Address]*big.Int{ cChainUSDC.Address(): tinyOneCoin, }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + }, + { + Name: "USDC programmable token transfer with too little gas", + Receiver: state.Chains[chainB].Receiver.Address(), + SourceChain: chainC, + DestChain: chainB, + Tokens: []router.ClientEVMTokenAmount{ + { + Token: cChainUSDC.Address(), + Amount: tinyOneCoin, + }, + }, + Data: []byte("gimme more gas to execute that!"), + ExpectedTokenBalances: map[common.Address]*big.Int{ + bChainUSDC.Address(): new(big.Int).SetUint64(0), + }, + ExtraArgs: changeset.MakeEVMExtraArgsV2(1, false), + ExpectedStatus: changeset.EXECUTION_STATE_FAILURE, + }, + { + Name: "USDC token transfer from a different source chain", + Receiver: utils.RandomAddress(), + SourceChain: chainB, + DestChain: chainC, + Tokens: []router.ClientEVMTokenAmount{ + { + Token: bChainUSDC.Address(), + Amount: tinyOneCoin, + }, + }, + Data: nil, + ExpectedTokenBalances: map[common.Address]*big.Int{ + cChainUSDC.Address(): tinyOneCoin, + }, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, }, } - for _, tt := range tcs { - t.Run(tt.name, func(t *testing.T) { - initialBalances := map[common.Address]*big.Int{} - for token := range tt.expectedTokenBalances { - initialBalance := getTokenBalance(t, token, tt.receiver, e.Chains[tt.destChain]) - initialBalances[token] = initialBalance - } - - transferAndWaitForSuccess( - t, - e, - state, - tt.sourceChain, - tt.destChain, - tt.tokens, - tt.receiver, - tt.data, - tt.expectedExecutionState, - ) - - for token, balance := range tt.expectedTokenBalances { - expected := new(big.Int).Add(initialBalances[token], balance) - waitForTheTokenBalance(t, token, tt.receiver, e.Chains[tt.destChain], expected) - } - }) - } - - t.Run("multi-source USDC transfer targeting the same dest receiver", func(t *testing.T) { - sendSingleTokenTransfer := func(source, dest uint64, token common.Address, receiver common.Address) (*onramp.OnRampCCIPMessageSent, changeset.SourceDestPair) { - msg := changeset.TestSendRequest(t, e, state, source, dest, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(receiver.Bytes(), 32), - Data: []byte{}, - TokenAmounts: []router.ClientEVMTokenAmount{{Token: token, Amount: tinyOneCoin}}, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - return msg, changeset.SourceDestPair{ - SourceChainSelector: source, - DestChainSelector: dest, - } - } - - receiver := utils.RandomAddress() - - startBlocks := make(map[uint64]*uint64) - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) - - latesthdr, err := e.Chains[chainC].Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[chainC] = &block + startBlocks, expectedSeqNums, expectedExecutionStates, expectedTokenBalances := + changeset.TransferMultiple(ctx, t, e, state, tcs) - message1, message1ID := sendSingleTokenTransfer(chainA, chainC, aChainUSDC.Address(), receiver) - expectedSeqNum[message1ID] = message1.SequenceNumber - expectedSeqNumExec[message1ID] = []uint64{message1.SequenceNumber} - - message2, message2ID := sendSingleTokenTransfer(chainB, chainC, bChainUSDC.Address(), receiver) - expectedSeqNum[message2ID] = message2.SequenceNumber - expectedSeqNumExec[message2ID] = []uint64{message2.SequenceNumber} - - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) - states := changeset.ConfirmExecWithSeqNrsForAll(t, e, state, expectedSeqNumExec, startBlocks) + err = changeset.ConfirmMultipleCommits( + t, + e.Chains, + state.Chains, + startBlocks, + false, + expectedSeqNums, + ) + require.NoError(t, err) - require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, states[message1ID][message1.SequenceNumber]) - require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, states[message2ID][message2.SequenceNumber]) + execStates := changeset.ConfirmExecWithSeqNrsForAll( + t, + e, + state, + changeset.SeqNumberRageToSlice(expectedSeqNums), + startBlocks, + ) + require.Equal(t, expectedExecutionStates, execStates) - // We sent 1 coin from each source chain, so we should have 2 coins on the destination chain - // Receiver is randomly generated so we don't need to get the initial balance first - expectedBalance := new(big.Int).Add(tinyOneCoin, tinyOneCoin) - waitForTheTokenBalance(t, cChainUSDC.Address(), receiver, e.Chains[chainC], expectedBalance) - }) + changeset.WaitForTokenBalances(ctx, t, e.Chains, expectedTokenBalances) } -// mintAndAllow mints tokens for deployers and allow router to spend them -func mintAndAllow( - t *testing.T, +func updateFeeQuoters( + lggr logger.Logger, e deployment.Environment, state changeset.CCIPOnChainState, - tkMap map[uint64][]*burn_mint_erc677.BurnMintERC677, -) { - for chain, tokens := range tkMap { - for _, token := range tokens { - twoCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2)) - - tx, err := token.Mint( - e.Chains[chain].DeployerKey, - e.Chains[chain].DeployerKey.From, - new(big.Int).Mul(twoCoins, big.NewInt(10)), - ) - require.NoError(t, err) - _, err = e.Chains[chain].Confirm(tx) - require.NoError(t, err) - - tx, err = token.Approve(e.Chains[chain].DeployerKey, state.Chains[chain].Router.Address(), twoCoins) - require.NoError(t, err) - _, err = e.Chains[chain].Confirm(tx) - require.NoError(t, err) + chainA, chainB, chainC uint64, + aChainUSDC, bChainUSDC, cChainUSDC *burn_mint_erc677.BurnMintERC677, +) error { + updateFeeQtrGrp := errgroup.Group{} + updateFeeQtrGrp.Go(func() error { + return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainA], state.Chains[chainA], chainC, aChainUSDC) + }) + updateFeeQtrGrp.Go(func() error { + return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainB], state.Chains[chainB], chainC, bChainUSDC) + }) + updateFeeQtrGrp.Go(func() error { + err1 := changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainA, cChainUSDC) + if err1 != nil { + return err1 } - } -} - -// transferAndWaitForSuccess sends a message from sourceChain to destChain and waits for it to be executed -func transferAndWaitForSuccess( - t *testing.T, - env deployment.Environment, - state changeset.CCIPOnChainState, - sourceChain, destChain uint64, - tokens []router.ClientEVMTokenAmount, - receiver common.Address, - data []byte, - expectedStatus int, -) { - identifier := changeset.SourceDestPair{ - SourceChainSelector: sourceChain, - DestChainSelector: destChain, - } - - startBlocks := make(map[uint64]*uint64) - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) - - latesthdr, err := env.Chains[destChain].Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[destChain] = &block - - msgSentEvent := changeset.TestSendRequest(t, env, state, sourceChain, destChain, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(receiver.Bytes(), 32), - Data: data, - TokenAmounts: tokens, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, + return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainB, cChainUSDC) }) - expectedSeqNum[identifier] = msgSentEvent.SequenceNumber - expectedSeqNumExec[identifier] = []uint64{msgSentEvent.SequenceNumber} - - // Wait for all commit reports to land. - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, env, state, expectedSeqNum, startBlocks) - - // Wait for all exec reports to land - states := changeset.ConfirmExecWithSeqNrsForAll(t, env, state, expectedSeqNumExec, startBlocks) - require.Equal(t, expectedStatus, states[identifier][msgSentEvent.SequenceNumber]) -} - -func waitForTheTokenBalance( - t *testing.T, - token common.Address, - receiver common.Address, - chain deployment.Chain, - expected *big.Int, -) { - tokenContract, err := burn_mint_erc677.NewBurnMintERC677(token, chain.Client) - require.NoError(t, err) - - require.Eventually(t, func() bool { - actualBalance, err := tokenContract.BalanceOf(&bind.CallOpts{Context: tests.Context(t)}, receiver) - require.NoError(t, err) - - t.Log("Waiting for the token balance", - "expected", expected, - "actual", actualBalance, - "token", token, - "receiver", receiver, - ) - - return actualBalance.Cmp(expected) == 0 - }, tests.WaitTimeout(t), 100*time.Millisecond) -} - -func getTokenBalance( - t *testing.T, - token common.Address, - receiver common.Address, - chain deployment.Chain, -) *big.Int { - tokenContract, err := burn_mint_erc677.NewBurnMintERC677(token, chain.Client) - require.NoError(t, err) - - balance, err := tokenContract.BalanceOf(&bind.CallOpts{Context: tests.Context(t)}, receiver) - require.NoError(t, err) - - t.Log("Getting token balance", - "actual", balance, - "token", token, - "receiver", receiver, - ) - - return balance + return updateFeeQtrGrp.Wait() } diff --git a/integration-tests/smoke/ccip/fee_boosting_test.go b/integration-tests/smoke/ccip/fee_boosting_test.go deleted file mode 100644 index 918ac243ab8..00000000000 --- a/integration-tests/smoke/ccip/fee_boosting_test.go +++ /dev/null @@ -1,121 +0,0 @@ -package smoke - -import ( - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/test-go/testify/require" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -type feeboostTestCase struct { - t *testing.T - sender []byte - deployedEnv changeset.DeployedEnv - onchainState changeset.CCIPOnChainState - initialPrices changeset.InitialPrices - priceFeedPrices priceFeedPrices - sourceChain, destChain uint64 -} - -type priceFeedPrices struct { - linkPrice *big.Int - wethPrice *big.Int -} - -// TODO: find a way to reuse the same test setup for all tests -func Test_CCIPFeeBoosting(t *testing.T) { - setupTestEnv := func(t *testing.T, numChains int) (changeset.DeployedEnv, changeset.CCIPOnChainState, []uint64) { - e, _, _ := testsetups.NewLocalDevEnvironment(t, logger.TestLogger(t), deployment.E18Mult(5), big.NewInt(9e8), nil) - - state, err := changeset.LoadOnchainState(e.Env) - require.NoError(t, err) - - allChainSelectors := maps.Keys(e.Env.Chains) - require.Len(t, allChainSelectors, numChains) - return e, state, allChainSelectors - } - - t.Run("boost needed due to WETH price increase (also covering gas price inscrease)", func(t *testing.T) { - e, state, chains := setupTestEnv(t, 2) - runFeeboostTestCase(feeboostTestCase{ - t: t, - sender: common.LeftPadBytes(e.Env.Chains[chains[0]].DeployerKey.From.Bytes(), 32), - deployedEnv: e, - onchainState: state, - initialPrices: changeset.InitialPrices{ - LinkPrice: deployment.E18Mult(5), - WethPrice: deployment.E18Mult(9), - GasPrice: changeset.ToPackedFee(big.NewInt(1.8e11), big.NewInt(0)), - }, - priceFeedPrices: priceFeedPrices{ - linkPrice: deployment.E18Mult(5), - wethPrice: big.NewInt(9.9e8), // increase from 9e8 to 9.9e8 - }, - sourceChain: chains[0], - destChain: chains[1], - }) - }) - - t.Run("boost needed due to LINK price decrease", func(t *testing.T) { - e, state, chains := setupTestEnv(t, 2) - runFeeboostTestCase(feeboostTestCase{ - t: t, - sender: common.LeftPadBytes(e.Env.Chains[chains[0]].DeployerKey.From.Bytes(), 32), - deployedEnv: e, - onchainState: state, - initialPrices: changeset.InitialPrices{ - LinkPrice: deployment.E18Mult(5), - WethPrice: deployment.E18Mult(9), - GasPrice: changeset.ToPackedFee(big.NewInt(1.8e11), big.NewInt(0)), - }, - priceFeedPrices: priceFeedPrices{ - linkPrice: big.NewInt(4.5e18), // decrease from 5e18 to 4.5e18 - wethPrice: big.NewInt(9e8), - }, - sourceChain: chains[0], - destChain: chains[1], - }) - }) -} - -func runFeeboostTestCase(tc feeboostTestCase) { - require.NoError(tc.t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(tc.deployedEnv.Env, tc.onchainState, tc.sourceChain, tc.destChain, false)) - - startBlocks := make(map[uint64]*uint64) - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) - msgSentEvent := changeset.TestSendRequest(tc.t, tc.deployedEnv.Env, tc.onchainState, tc.sourceChain, tc.destChain, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(tc.onchainState.Chains[tc.destChain].Receiver.Address().Bytes(), 32), - Data: []byte("message that needs fee boosting"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - expectedSeqNum[changeset.SourceDestPair{ - SourceChainSelector: tc.sourceChain, - DestChainSelector: tc.destChain, - }] = msgSentEvent.SequenceNumber - expectedSeqNumExec[changeset.SourceDestPair{ - SourceChainSelector: tc.sourceChain, - DestChainSelector: tc.destChain, - }] = []uint64{msgSentEvent.SequenceNumber} - - // hack - time.Sleep(30 * time.Second) - replayBlocks := make(map[uint64]uint64) - replayBlocks[tc.sourceChain] = 1 - replayBlocks[tc.destChain] = 1 - changeset.ReplayLogs(tc.t, tc.deployedEnv.Env.Offchain, replayBlocks) - - changeset.ConfirmCommitForAllWithExpectedSeqNums(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNum, startBlocks) - changeset.ConfirmExecWithSeqNrsForAll(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNumExec, startBlocks) -} diff --git a/integration-tests/testconfig/ccip/ccip.toml b/integration-tests/testconfig/ccip/ccip.toml index 85e645ed0b9..3f4ba43c48c 100644 --- a/integration-tests/testconfig/ccip/ccip.toml +++ b/integration-tests/testconfig/ccip/ccip.toml @@ -9,8 +9,17 @@ selected_networks = ['SIMULATED_1', 'SIMULATED_2'] evm_name = 'chain-1337' evm_chain_id = 1337 evm_keys = [ - "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", + "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", + "7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", + "47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", + "8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", + "92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", + "4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", + "dbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", + "2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", + "f214f2b2cd398c806f84e317254e0f0b801d0643303237d97a22a48e01628897" ] evm_simulated = true client_implementation = 'Ethereum' @@ -28,6 +37,15 @@ evm_chain_id = 2337 evm_keys = [ "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", + "7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", + "47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", + "8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", + "92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", + "4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", + "dbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", + "2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", + "f214f2b2cd398c806f84e317254e0f0b801d0643303237d97a22a48e01628897" ] evm_simulated = true client_implementation = 'Ethereum' @@ -45,6 +63,15 @@ evm_chain_id = 3337 evm_keys = [ "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", + "7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", + "47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", + "8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", + "92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", + "4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", + "dbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", + "2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", + "f214f2b2cd398c806f84e317254e0f0b801d0643303237d97a22a48e01628897" ] evm_simulated = true client_implementation = 'Ethereum' @@ -144,6 +171,15 @@ chain_id = 1337 addresses_to_fund = [ "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "0x90f79bf6eb2c4f870365e785982e1f101e93b906", + "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65", + "0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "0x976ea74026e726554db657fa54763abd0c3a0aa9", + "0x14dc79964da2c08b23698b3d3cc7ca32193d9955", + "0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f", + "0xa0ee7a142d267c1f36714e4a8f75612f20a79720", + "0xBcd4042DE499D14e55001CcbB24a551F3b954096" ] @@ -166,6 +202,15 @@ chain_id = 2337 addresses_to_fund = [ "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "0x90f79bf6eb2c4f870365e785982e1f101e93b906", + "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65", + "0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "0x976ea74026e726554db657fa54763abd0c3a0aa9", + "0x14dc79964da2c08b23698b3d3cc7ca32193d9955", + "0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f", + "0xa0ee7a142d267c1f36714e4a8f75612f20a79720", + "0xBcd4042DE499D14e55001CcbB24a551F3b954096" ] [CCIP.PrivateEthereumNetworks.SIMULATED_3] @@ -181,6 +226,15 @@ chain_id = 3337 addresses_to_fund = [ "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "0x90f79bf6eb2c4f870365e785982e1f101e93b906", + "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65", + "0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "0x976ea74026e726554db657fa54763abd0c3a0aa9", + "0x14dc79964da2c08b23698b3d3cc7ca32193d9955", + "0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f", + "0xa0ee7a142d267c1f36714e4a8f75612f20a79720", + "0xBcd4042DE499D14e55001CcbB24a551F3b954096" ] [Seth] diff --git a/integration-tests/testconfig/ccip/config.go b/integration-tests/testconfig/ccip/config.go index 6c1bfcbe560..72c81f05f47 100644 --- a/integration-tests/testconfig/ccip/config.go +++ b/integration-tests/testconfig/ccip/config.go @@ -8,8 +8,6 @@ import ( "github.com/AlekSi/pointer" chainselectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient" @@ -147,40 +145,46 @@ func (o *JDConfig) GetJDDBVersion() string { } func (o *Config) Validate() error { - return nil -} - -func (o *Config) GetHomeChainSelector(evmNetworks []blockchain.EVMNetwork) (uint64, error) { + var chainIds []int64 + for _, net := range o.PrivateEthereumNetworks { + chainIds = append(chainIds, int64(net.EthereumChainConfig.ChainID)) + } homeChainSelector, err := strconv.ParseUint(pointer.GetString(o.HomeChainSelector), 10, 64) if err != nil { - return 0, err + return err } - isValid, err := IsSelectorValid(homeChainSelector, evmNetworks) + isValid, err := IsSelectorValid(homeChainSelector, chainIds) if err != nil { - return 0, err + return err } if !isValid { - return 0, ErrInvalidHomeChainSelector + return ErrInvalidHomeChainSelector } - return homeChainSelector, nil -} - -func (o *Config) GetFeedChainSelector(evmNetworks []blockchain.EVMNetwork) (uint64, error) { feedChainSelector, err := strconv.ParseUint(pointer.GetString(o.FeedChainSelector), 10, 64) if err != nil { - return 0, err + return err } - isValid, err := IsSelectorValid(feedChainSelector, evmNetworks) + isValid, err = IsSelectorValid(feedChainSelector, chainIds) if err != nil { - return 0, err + return err } if !isValid { - return 0, ErrInvalidFeedChainSelector + return ErrInvalidFeedChainSelector } - return feedChainSelector, nil + return nil +} + +func (o *Config) GetHomeChainSelector() uint64 { + selector, _ := strconv.ParseUint(pointer.GetString(o.HomeChainSelector), 10, 64) + return selector +} + +func (o *Config) GetFeedChainSelector() uint64 { + selector, _ := strconv.ParseUint(pointer.GetString(o.FeedChainSelector), 10, 64) + return selector } -func IsSelectorValid(selector uint64, evmNetworks []blockchain.EVMNetwork) (bool, error) { +func IsSelectorValid(selector uint64, chainIds []int64) (bool, error) { chainId, err := chainselectors.ChainIdFromSelector(selector) if err != nil { return false, err @@ -188,9 +192,9 @@ func IsSelectorValid(selector uint64, evmNetworks []blockchain.EVMNetwork) (bool if chainId >= math.MaxInt64 { return false, fmt.Errorf("chain id overflows int64: %d", chainId) } - id := int64(chainId) - for _, net := range evmNetworks { - if net.ChainID == id { + expId := int64(chainId) + for _, id := range chainIds { + if id == expId { return true, nil } } diff --git a/integration-tests/testsetups/ccip/test_helpers.go b/integration-tests/testsetups/ccip/test_helpers.go index b2084f17dd1..3112d738869 100644 --- a/integration-tests/testsetups/ccip/test_helpers.go +++ b/integration-tests/testsetups/ccip/test_helpers.go @@ -2,6 +2,7 @@ package ccip import ( "bytes" + "context" "fmt" "math/big" "os" @@ -9,12 +10,12 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" chainsel "github.com/smartcontractkit/chain-selectors" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" @@ -34,6 +35,14 @@ import ( evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" corechainlink "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/AlekSi/pointer" + "github.com/ethereum/go-ethereum/common" + "github.com/rs/zerolog" + "github.com/stretchr/testify/require" + "github.com/subosito/gotenv" + "golang.org/x/sync/errgroup" + "google.golang.org/grpc/credentials/insecure" + "github.com/smartcontractkit/chainlink/deployment/environment/devenv" clclient "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient" "github.com/smartcontractkit/chainlink/integration-tests/actions" @@ -43,17 +52,6 @@ import ( tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - - "github.com/AlekSi/pointer" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/rs/zerolog" - "github.com/stretchr/testify/require" - "github.com/subosito/gotenv" - "golang.org/x/sync/errgroup" - "google.golang.org/grpc/credentials/insecure" ) // DeployedLocalDevEnvironment is a helper struct for setting up a local dev environment with docker @@ -104,12 +102,18 @@ func NewLocalDevEnvironment( require.NotNil(t, envConfig) require.NotEmpty(t, envConfig.Chains, "chainConfigs should not be empty") require.NotEmpty(t, envConfig.JDConfig, "jdUrl should not be empty") + users := make(map[uint64][]*bind.TransactOpts) + for _, chain := range envConfig.Chains { + sel, err := chainsel.SelectorFromChainId(chain.ChainID) + require.NoError(t, err) + users[sel] = chain.Users + } chains, err := devenv.NewChains(lggr, envConfig.Chains) require.NoError(t, err) // locate the home chain - homeChainSel := envConfig.HomeChainSelector + homeChainSel := cfg.CCIP.GetHomeChainSelector() require.NotEmpty(t, homeChainSel, "homeChainSel should not be empty") - feedSel := envConfig.FeedChainSelector + feedSel := cfg.CCIP.GetFeedChainSelector() require.NotEmpty(t, feedSel, "feedSel should not be empty") replayBlocks, err := changeset.LatestBlocksByChain(ctx, chains) require.NoError(t, err) @@ -123,7 +127,7 @@ func NewLocalDevEnvironment( testEnv, cfg) require.NoError(t, err) - e, don, err := devenv.NewEnvironment(ctx, lggr, *envConfig) + e, don, err := devenv.NewEnvironment(func() context.Context { return ctx }, lggr, *envConfig) require.NoError(t, err) require.NotNil(t, e) e.ExistingAddresses = ab @@ -140,16 +144,15 @@ func NewLocalDevEnvironment( if tCfg.IsUSDC { usdcChains = allChains } - mcmsCfgPerChain := commontypes.MCMSWithTimelockConfig{ - Canceller: commonchangeset.SingleGroupMCMS(t), - Bypasser: commonchangeset.SingleGroupMCMS(t), - Proposer: commonchangeset.SingleGroupMCMS(t), - TimelockExecutors: env.AllDeployerKeys(), - TimelockMinDelay: big.NewInt(0), - } mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) for _, c := range env.AllChainSelectors() { - mcmsCfg[c] = mcmsCfgPerChain + mcmsCfg[c] = commontypes.MCMSWithTimelockConfig{ + Canceller: commonchangeset.SingleGroupMCMS(t), + Bypasser: commonchangeset.SingleGroupMCMS(t), + Proposer: commonchangeset.SingleGroupMCMS(t), + TimelockExecutors: env.AllDeployerKeys(), + TimelockMinDelay: big.NewInt(0), + } } // Need to deploy prerequisites first so that we can form the USDC config // no proposals to be made, timelock can be passed as nil here @@ -166,6 +169,10 @@ func NewLocalDevEnvironment( }, }, }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: allChains, + }, { Changeset: commonchangeset.WrapChangeSet(changeset.DeployPrerequisites), Config: changeset.DeployPrerequisiteConfig{ @@ -189,58 +196,55 @@ func NewLocalDevEnvironment( }, }) require.NoError(t, err) - state, err := changeset.LoadOnchainState(env) require.NoError(t, err) - tokenConfig := changeset.NewTestTokenConfig(state.Chains[feedSel].USDFeeds) - usdcCCTPConfig := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig) - timelocksPerChain := make(map[uint64]*gethwrappers.RBACTimelock) - ocrParams := make(map[uint64]changeset.CCIPOCRParams) - for _, chain := range usdcChains { - require.NotNil(t, state.Chains[chain].MockUSDCTokenMessenger) - require.NotNil(t, state.Chains[chain].MockUSDCTransmitter) - require.NotNil(t, state.Chains[chain].USDCTokenPool) - usdcCCTPConfig[cciptypes.ChainSelector(chain)] = pluginconfig.USDCCCTPTokenConfig{ - SourcePoolAddress: state.Chains[chain].USDCTokenPool.Address().String(), - SourceMessageTransmitterAddr: state.Chains[chain].MockUSDCTransmitter.Address().String(), - } - } - var usdcAttestationCfg changeset.USDCAttestationConfig + + var tokenDataProviders []pluginconfig.TokenDataObserverConfig if len(usdcChains) > 0 { var endpoint string - err = ccipactions.SetMockServerWithUSDCAttestation(testEnv.MockAdapter, nil) + err = ccipactions.SetMockServerWithUSDCAttestation(testEnv.MockAdapter, nil, tCfg.IsUSDCAttestationMissing) require.NoError(t, err) endpoint = testEnv.MockAdapter.InternalEndpoint - usdcAttestationCfg = changeset.USDCAttestationConfig{ - API: endpoint, - APITimeout: commonconfig.MustNewDuration(time.Second), - APIInterval: commonconfig.MustNewDuration(500 * time.Millisecond), + cctpContracts := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig) + for _, usdcChain := range usdcChains { + cctpContracts[cciptypes.ChainSelector(usdcChain)] = pluginconfig.USDCCCTPTokenConfig{ + SourcePoolAddress: state.Chains[usdcChain].USDCTokenPool.Address().String(), + SourceMessageTransmitterAddr: state.Chains[usdcChain].MockUSDCTransmitter.Address().String(), + } } - } - require.NotNil(t, state.Chains[feedSel].LinkToken) - require.NotNil(t, state.Chains[feedSel].Weth9) - + tokenDataProviders = append(tokenDataProviders, pluginconfig.TokenDataObserverConfig{ + Type: pluginconfig.USDCCCTPHandlerType, + Version: "1.0", + USDCCCTPObserverConfig: &pluginconfig.USDCCCTPObserverConfig{ + Tokens: cctpContracts, + AttestationAPI: endpoint, + AttestationAPITimeout: commonconfig.MustNewDuration(time.Second), + AttestationAPIInterval: commonconfig.MustNewDuration(500 * time.Millisecond), + }}) + } + + // Build the per chain config. + tokenConfig := changeset.NewTestTokenConfig(state.Chains[feedSel].USDFeeds) + chainConfigs := make(map[uint64]changeset.CCIPOCRParams) + timelocksPerChain := make(map[uint64]*gethwrappers.RBACTimelock) for _, chain := range allChains { timelocksPerChain[chain] = state.Chains[chain].Timelock - tokenInfo := tokenConfig.GetTokenInfo(env.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9) - ocrParams[chain] = changeset.DefaultOCRParams(feedSel, tokenInfo) + tokenInfo := tokenConfig.GetTokenInfo(e.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9) + ocrParams := changeset.DefaultOCRParams(feedSel, tokenInfo, tokenDataProviders) + if tCfg.OCRConfigOverride != nil { + ocrParams = tCfg.OCRConfigOverride(ocrParams) + } + chainConfigs[chain] = ocrParams } + // Deploy second set of changesets to deploy and configure the CCIP contracts. env, err = commonchangeset.ApplyChangesets(t, env, timelocksPerChain, []commonchangeset.ChangesetApplication{ { Changeset: commonchangeset.WrapChangeSet(changeset.ConfigureNewChains), Config: changeset.NewChainsConfig{ - HomeChainSel: homeChainSel, - FeedChainSel: feedSel, - ChainsToDeploy: allChains, - TokenConfig: tokenConfig, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), - OCRParams: ocrParams, - USDCConfig: changeset.USDCConfig{ - EnabledChains: usdcChains, - USDCAttestationConfig: usdcAttestationCfg, - CCTPTokenConfig: usdcCCTPConfig, - }, + HomeChainSel: homeChainSel, + FeedChainSel: feedSel, + ChainConfigByChain: chainConfigs, }, }, { @@ -257,6 +261,7 @@ func NewLocalDevEnvironment( HomeChainSel: homeChainSel, FeedChainSel: feedSel, ReplayBlocks: replayBlocks, + Users: users, }, testEnv, cfg } @@ -463,16 +468,9 @@ func CreateDockerEnv(t *testing.T) ( } require.NotEmpty(t, jdConfig, "JD config is empty") - homeChainSelector, err := cfg.CCIP.GetHomeChainSelector(evmNetworks) - require.NoError(t, err, "Error getting home chain selector") - feedChainSelector, err := cfg.CCIP.GetFeedChainSelector(evmNetworks) - require.NoError(t, err, "Error getting feed chain selector") - return &devenv.EnvironmentConfig{ - Chains: chains, - JDConfig: jdConfig, - HomeChainSelector: homeChainSelector, - FeedChainSelector: feedChainSelector, + Chains: chains, + JDConfig: jdConfig, }, env, cfg } @@ -518,7 +516,7 @@ func StartChainlinkNodes( cfg.NodeConfig.ChainConfigTOMLByChainID, ) - toml.Capabilities.ExternalRegistry.NetworkID = ptr.Ptr(relay.NetworkEVM) + toml.Capabilities.ExternalRegistry.NetworkID = ptr.Ptr(registryConfig.NetworkType) toml.Capabilities.ExternalRegistry.ChainID = ptr.Ptr(strconv.FormatUint(registryConfig.EVMChainID, 10)) toml.Capabilities.ExternalRegistry.Address = ptr.Ptr(registryConfig.Contract.String()) @@ -650,7 +648,7 @@ func FundNodes(t *testing.T, lggr zerolog.Logger, env *test_env.CLClusterTestEnv require.NoError(t, fundGrp.Wait(), "Error funding chainlink nodes") } -// CreateChainConfigFromNetworks creates a list of ChainConfig from the network config provided in test config. +// CreateChainConfigFromNetworks creates a list of CCIPOCRParams from the network config provided in test config. // It either creates it from the private ethereum networks created by the test environment or from the // network URLs provided in the network config ( if the network is a live testnet). // It uses the private keys from the network config to create the deployer key for each chain. @@ -661,62 +659,73 @@ func CreateChainConfigFromNetworks( networkConfig *ctfconfig.NetworkConfig, ) []devenv.ChainConfig { evmNetworks := networks.MustGetSelectedNetworkConfig(networkConfig) - networkPvtKeys := make(map[int64]string) + networkPvtKeys := make(map[uint64][]string) for _, net := range evmNetworks { require.Greater(t, len(net.PrivateKeys), 0, "No private keys found for network") - networkPvtKeys[net.ChainID] = net.PrivateKeys[0] + if net.ChainID < 0 { + t.Fatalf("negative chain ID: %d", net.ChainID) + } + networkPvtKeys[uint64(net.ChainID)] = net.PrivateKeys + } + type chainDetails struct { + chainId uint64 + wsRPCs []string + httpRPCs []string } var chains []devenv.ChainConfig - // if private ethereum networks are not provided, we will create chains from the network URLs + var chaindetails []chainDetails if len(privateEthereumNetworks) == 0 { for _, net := range evmNetworks { chainId := net.ChainID if chainId < 0 { t.Fatalf("negative chain ID: %d", chainId) } - chainName, err := chainsel.NameFromChainId(uint64(chainId)) - require.NoError(t, err, "Error getting chain name") - pvtKeyStr, exists := networkPvtKeys[chainId] - require.Truef(t, exists, "Private key not found for chain id %d", chainId) - pvtKey, err := crypto.HexToECDSA(pvtKeyStr) - require.NoError(t, err) - deployer, err := bind.NewKeyedTransactorWithChainID(pvtKey, big.NewInt(chainId)) - require.NoError(t, err) - deployer.GasLimit = net.DefaultGasLimit - chains = append(chains, devenv.ChainConfig{ - ChainID: uint64(chainId), - ChainName: chainName, - ChainType: "EVM", - WSRPCs: net.URLs, - HTTPRPCs: net.HTTPURLs, - DeployerKey: deployer, + chaindetails = append(chaindetails, chainDetails{ + chainId: uint64(chainId), + wsRPCs: net.URLs, + httpRPCs: net.HTTPURLs, + }) + } + } else { + for _, net := range privateEthereumNetworks { + chainId := net.EthereumChainConfig.ChainID + if chainId < 0 { + t.Fatalf("negative chain ID: %d", chainId) + } + rpcProvider, err := env.GetRpcProvider(int64(chainId)) + require.NoError(t, err, "Error getting rpc provider") + chaindetails = append(chaindetails, chainDetails{ + chainId: uint64(chainId), + wsRPCs: rpcProvider.PublicWsUrls(), + httpRPCs: rpcProvider.PublicHttpUrls(), }) } - return chains } - for _, networkCfg := range privateEthereumNetworks { - chainId := networkCfg.EthereumChainConfig.ChainID - chainName, err := chainsel.NameFromChainId(uint64(chainId)) + for _, cd := range chaindetails { + chainId := cd.chainId + chainName, err := chainsel.NameFromChainId(chainId) require.NoError(t, err, "Error getting chain name") - rpcProvider, err := env.GetRpcProvider(int64(chainId)) - require.NoError(t, err, "Error getting rpc provider") - pvtKeyStr, exists := networkPvtKeys[int64(chainId)] - require.Truef(t, exists, "Private key not found for chain id %d", chainId) - pvtKey, err := crypto.HexToECDSA(pvtKeyStr) - require.NoError(t, err) - deployer, err := bind.NewKeyedTransactorWithChainID(pvtKey, big.NewInt(int64(chainId))) - require.NoError(t, err) - if chainId < 0 { - t.Fatalf("negative chain ID: %d", chainId) + chainCfg := devenv.ChainConfig{ + ChainID: chainId, + ChainName: chainName, + ChainType: "EVM", + WSRPCs: cd.wsRPCs, + HTTPRPCs: cd.httpRPCs, } - chains = append(chains, devenv.ChainConfig{ - ChainID: uint64(chainId), - ChainName: chainName, - ChainType: devenv.EVMChainType, - WSRPCs: rpcProvider.PublicWsUrls(), - HTTPRPCs: rpcProvider.PublicHttpUrls(), - DeployerKey: deployer, - }) + var pvtKey *string + // if private keys are provided, use the first private key as deployer key + // otherwise it will try to load the private key from KMS + if len(networkPvtKeys[chainId]) > 0 { + pvtKey = ptr.Ptr(networkPvtKeys[chainId][0]) + } + require.NoError(t, chainCfg.SetDeployerKey(pvtKey), "Error setting deployer key") + var additionalPvtKeys []string + if len(networkPvtKeys[chainId]) > 1 { + additionalPvtKeys = networkPvtKeys[chainId][1:] + } + // if no additional private keys are provided, this will set the users to default deployer key + require.NoError(t, chainCfg.SetUsers(additionalPvtKeys), "Error setting users") + chains = append(chains, chainCfg) } return chains } diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index 69da49ae404..7a90c38fdd0 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -64,13 +64,14 @@ type OCRSoakTest struct { Config *tc.TestConfig TestReporter testreporters.OCRSoakTestReporter OperatorForwarderFlow bool - seth *seth.Client + sethClient *seth.Client OCRVersion string t *testing.T startTime time.Time timeLeft time.Duration startingBlockNum uint64 + startingValue int testEnvironment *environment.Environment namespace string log zerolog.Logger @@ -88,6 +89,8 @@ type OCRSoakTest struct { ocrV2Instances []contracts.OffchainAggregatorV2 ocrV2InstanceMap map[string]contracts.OffchainAggregatorV2 // address : instance + linkContract *contracts.EthereumLinkToken + rpcNetwork blockchain.EVMNetwork // network configuration for the blockchain node reorgHappened bool // flag to indicate if a reorg happened during the test gasSpikeSimulationHappened bool // flag to indicate if a gas spike simulation happened during the test @@ -160,11 +163,21 @@ func (o *OCRSoakTest) DeployEnvironment(ocrTestConfig tt.OcrTestConfig) { nsPre = fmt.Sprintf("%s%s", nsPre, strings.ReplaceAll(strings.ToLower(nodeNetwork.Name), " ", "-")) nsPre = strings.ReplaceAll(nsPre, "_", "-") + productName := fmt.Sprintf("data-feedsv%s.0", o.OCRVersion) + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(productName, "soak") + require.NoError(o.t, err, "Error creating required chain.link labels for namespace") + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(productName, "soak") + require.NoError(o.t, err, "Error creating required chain.link labels for workloads and pods") + baseEnvironmentConfig := &environment.Config{ TTL: time.Hour * 720, // 30 days, NamespacePrefix: nsPre, Test: o.t, PreventPodEviction: true, + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, } testEnv := environment.New(baseEnvironmentConfig). @@ -270,107 +283,151 @@ func (o *OCRSoakTest) Environment() *environment.Environment { return o.testEnvironment } +// Setup initializes the OCR Soak Test by setting up clients, funding nodes, and deploying OCR contracts. func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { + o.initializeClients() + o.deployLinkTokenContract(ocrTestConfig) + o.fundChainlinkNodes() + + o.startingValue = 5 + + var forwarders []common.Address + if o.OperatorForwarderFlow { + _, forwarders = o.deployForwarderContracts() + } + + o.setupOCRContracts(ocrTestConfig, forwarders) + o.log.Info().Msg("OCR Soak Test Setup Complete") +} + +// initializeClients sets up the Seth client, Chainlink nodes, and mock server. +func (o *OCRSoakTest) initializeClients() { sethClient, err := seth_utils.GetChainClient(o.Config, o.rpcNetwork) require.NoError(o.t, err, "Error creating seth client") - o.seth = sethClient + o.sethClient = sethClient nodes, err := nodeclient.ConnectChainlinkNodes(o.testEnvironment) require.NoError(o.t, err, "Connecting to chainlink nodes shouldn't fail") o.bootstrapNode, o.workerNodes = nodes[0], nodes[1:] + o.mockServer = ctf_client.ConnectMockServer(o.testEnvironment) require.NoError(o.t, err, "Creating mockserver clients shouldn't fail") +} - linkContract, err := actions.LinkTokenContract(o.log, sethClient, ocrTestConfig.GetActiveOCRConfig()) +func (o *OCRSoakTest) deployLinkTokenContract(ocrTestConfig tt.OcrTestConfig) { + linkContract, err := actions.LinkTokenContract(o.log, o.sethClient, ocrTestConfig.GetActiveOCRConfig()) require.NoError(o.t, err, "Error loading/deploying link token contract") + o.linkContract = linkContract +} - // Fund Chainlink nodes, excluding the bootstrap node +// fundChainlinkNodes funds the Chainlink worker nodes. +func (o *OCRSoakTest) fundChainlinkNodes() { o.log.Info().Float64("ETH amount per node", *o.Config.Common.ChainlinkNodeFunding).Msg("Funding Chainlink nodes") - err = actions.FundChainlinkNodesFromRootAddress(o.log, sethClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), big.NewFloat(*o.Config.Common.ChainlinkNodeFunding)) + err := actions.FundChainlinkNodesFromRootAddress(o.log, o.sethClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), big.NewFloat(*o.Config.Common.ChainlinkNodeFunding)) require.NoError(o.t, err, "Error funding Chainlink nodes") +} - var forwarders []common.Address - if o.OperatorForwarderFlow { - var operators []common.Address - operators, forwarders, _ = actions.DeployForwarderContracts( - o.t, o.seth, common.HexToAddress(linkContract.Address()), len(o.workerNodes), - ) - require.Equal(o.t, len(o.workerNodes), len(operators), "Number of operators should match number of nodes") - require.Equal(o.t, len(o.workerNodes), len(forwarders), "Number of authorized forwarders should match number of nodes") - forwarderNodesAddresses, err := actions.ChainlinkNodeAddresses(o.workerNodes) - require.NoError(o.t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") - for i := range o.workerNodes { - actions.AcceptAuthorizedReceiversOperator( - o.t, o.log, o.seth, operators[i], forwarders[i], []common.Address{forwarderNodesAddresses[i]}) - require.NoError(o.t, err, "Accepting Authorize Receivers on Operator shouldn't fail") - actions.TrackForwarder(o.t, o.seth, forwarders[i], o.workerNodes[i]) - } - } else if o.OCRVersion == "1" { - if o.OperatorForwarderFlow { - o.ocrV1Instances, err = actions.DeployOCRContractsForwarderFlow( - o.log, - o.seth, - o.Config.GetActiveOCRConfig(), - common.HexToAddress(linkContract.Address()), - contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), - forwarders, - ) - require.NoError(o.t, err, "Error deploying OCR Forwarder contracts") - } else { - o.ocrV1Instances, err = actions.SetupOCRv1Contracts( - o.log, - sethClient, - o.Config.GetActiveOCRConfig(), - common.HexToAddress(linkContract.Address()), - contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), - ) - require.NoError(o.t, err) - } - } else if o.OCRVersion == "2" { - var transmitters []string +// deployForwarderContracts deploys forwarder contracts if OperatorForwarderFlow is enabled. +func (o *OCRSoakTest) deployForwarderContracts() (operators []common.Address, forwarders []common.Address) { + operators, forwarders, _ = actions.DeployForwarderContracts( + o.t, o.sethClient, common.HexToAddress(o.linkContract.Address()), len(o.workerNodes), + ) + require.Equal(o.t, len(o.workerNodes), len(operators), "Number of operators should match number of nodes") + require.Equal(o.t, len(o.workerNodes), len(forwarders), "Number of authorized forwarders should match number of nodes") + + forwarderNodesAddresses, err := actions.ChainlinkNodeAddresses(o.workerNodes) + require.NoError(o.t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") + for i := range o.workerNodes { + actions.AcceptAuthorizedReceiversOperator(o.t, o.log, o.sethClient, operators[i], forwarders[i], []common.Address{forwarderNodesAddresses[i]}) + require.NoError(o.t, err, "Accepting Authorize Receivers on Operator shouldn't fail") + actions.TrackForwarder(o.t, o.sethClient, forwarders[i], o.workerNodes[i]) + } + return operators, forwarders +} - if o.OperatorForwarderFlow { - for _, forwarder := range forwarders { - transmitters = append(transmitters, forwarder.Hex()) - } - } else { - for _, node := range o.workerNodes { - nodeAddress, err := node.PrimaryEthAddress() - require.NoError(o.t, err, "Error getting node's primary ETH address") - transmitters = append(transmitters, nodeAddress) - } - } +// setupOCRContracts deploys and configures OCR contracts based on the version and forwarder flow. +func (o *OCRSoakTest) setupOCRContracts(ocrTestConfig tt.OcrTestConfig, forwarders []common.Address) { + if o.OCRVersion == "1" { + o.setupOCRv1Contracts(forwarders) + } else if o.OCRVersion == "2" { + o.setupOCRv2Contracts(ocrTestConfig, forwarders) + } +} - ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() - o.ocrV2Instances, err = actions.SetupOCRv2Contracts( +// setupOCRv1Contracts deploys and configures OCRv1 contracts based on the forwarder flow. +func (o *OCRSoakTest) setupOCRv1Contracts(forwarders []common.Address) { + var err error + if o.OperatorForwarderFlow { + o.ocrV1Instances, err = actions.DeployOCRContractsForwarderFlow( o.log, - o.seth, - ocrTestConfig.GetActiveOCRConfig(), - common.HexToAddress(linkContract.Address()), - transmitters, - ocrOffchainOptions, + o.sethClient, + o.Config.GetActiveOCRConfig(), + common.HexToAddress(o.linkContract.Address()), + contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), + forwarders, ) - require.NoError(o.t, err, "Error deploying OCRv2 contracts") - - if !ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() || (ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() && ocrTestConfig.GetActiveOCRConfig().ConfigureExistingOffChainAggregatorsContracts()) { - contractConfig, err := actions.BuildMedianOCR2Config(o.workerNodes, ocrOffchainOptions) - require.NoError(o.t, err, "Error building median config") - err = actions.ConfigureOCRv2AggregatorContracts(contractConfig, o.ocrV2Instances) - require.NoError(o.t, err, "Error configuring OCRv2 aggregator contracts") - } + require.NoError(o.t, err, "Error deploying OCR Forwarder contracts") + o.createJobsWithForwarder() + } else { + o.ocrV1Instances, err = actions.SetupOCRv1Contracts( + o.log, + o.sethClient, + o.Config.GetActiveOCRConfig(), + common.HexToAddress(o.linkContract.Address()), + contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), + ) + require.NoError(o.t, err, "Error setting up OCRv1 contracts") + err = o.createOCRv1Jobs() + require.NoError(o.t, err, "Error creating OCR jobs") } - if o.OCRVersion == "1" { - for _, ocrInstance := range o.ocrV1Instances { - o.ocrV1InstanceMap[ocrInstance.Address()] = ocrInstance + o.storeOCRInstancesV1() +} + +// setupOCRv2Contracts sets up and configures OCRv2 contracts. +func (o *OCRSoakTest) setupOCRv2Contracts(ocrTestConfig tt.OcrTestConfig, forwarders []common.Address) { + var err error + var transmitters []string + if o.OperatorForwarderFlow { + for _, forwarder := range forwarders { + transmitters = append(transmitters, forwarder.Hex()) } - } else if o.OCRVersion == "2" { - for _, ocrInstance := range o.ocrV2Instances { - o.ocrV2InstanceMap[ocrInstance.Address()] = ocrInstance + } else { + for _, node := range o.workerNodes { + nodeAddress, err := node.PrimaryEthAddress() + require.NoError(o.t, err, "Error getting node's primary ETH address") + transmitters = append(transmitters, nodeAddress) } } - o.log.Info().Msg("OCR Soak Test Setup Complete") + ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() + o.ocrV2Instances, err = actions.SetupOCRv2Contracts( + o.log, o.sethClient, ocrTestConfig.GetActiveOCRConfig(), common.HexToAddress(o.linkContract.Address()), transmitters, ocrOffchainOptions, + ) + require.NoError(o.t, err, "Error deploying OCRv2 contracts") + err = o.createOCRv2Jobs() + require.NoError(o.t, err, "Error creating OCR jobs") + if !ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() || (ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() && ocrTestConfig.GetActiveOCRConfig().ConfigureExistingOffChainAggregatorsContracts()) { + contractConfig, err := actions.BuildMedianOCR2Config(o.workerNodes, ocrOffchainOptions) + require.NoError(o.t, err, "Error building median config") + err = actions.ConfigureOCRv2AggregatorContracts(contractConfig, o.ocrV2Instances) + require.NoError(o.t, err, "Error configuring OCRv2 aggregator contracts") + } + o.storeOCRInstancesV2() +} + +// storeOCRInstancesV1 stores OCRv1 contract instances by their addresses. +func (o *OCRSoakTest) storeOCRInstancesV1() { + for _, ocrInstance := range o.ocrV1Instances { + o.ocrV1InstanceMap[ocrInstance.Address()] = ocrInstance + } +} + +// storeOCRInstancesV2 stores OCRv2 contract instances by their addresses. +func (o *OCRSoakTest) storeOCRInstancesV2() { + for _, ocrInstance := range o.ocrV2Instances { + o.ocrV2InstanceMap[ocrInstance.Address()] = ocrInstance + } } // Run starts the OCR soak test @@ -379,36 +436,52 @@ func (o *OCRSoakTest) Run() { require.NoError(o.t, err, "Error getting config") ctx, cancel := context.WithTimeout(testcontext.Get(o.t), time.Second*5) - latestBlockNum, err := o.seth.Client.BlockNumber(ctx) + latestBlockNum, err := o.sethClient.Client.BlockNumber(ctx) cancel() require.NoError(o.t, err, "Error getting current block number") o.startingBlockNum = latestBlockNum - startingValue := 5 - if o.OperatorForwarderFlow { - actions.CreateOCRJobsWithForwarder(o.t, o.ocrV1Instances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, o.seth.ChainID) - } else if o.OCRVersion == "1" { - ctx, cancel := context.WithTimeout(testcontext.Get(o.t), time.Second*5) - chainId, err := o.seth.Client.ChainID(ctx) - cancel() - require.NoError(o.t, err, "Error getting chain ID") - err = actions.CreateOCRJobs(o.ocrV1Instances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, chainId.String()) - require.NoError(o.t, err, "Error creating OCR jobs") - } else if o.OCRVersion == "2" { - err := actions.CreateOCRv2Jobs(o.ocrV2Instances, o.bootstrapNode, o.workerNodes, o.mockServer, startingValue, o.seth.ChainID, o.OperatorForwarderFlow) - require.NoError(o.t, err, "Error creating OCR jobs") - } - o.log.Info(). Str("Test Duration", o.Config.GetActiveOCRConfig().Common.TestDuration.Duration.Truncate(time.Second).String()). Int("Number of OCR Contracts", *config.GetActiveOCRConfig().Common.NumberOfContracts). Str("OCR Version", o.OCRVersion). Msg("Starting OCR Soak Test") - o.testLoop(o.Config.GetActiveOCRConfig().Common.TestDuration.Duration, startingValue) + o.testLoop(o.Config.GetActiveOCRConfig().Common.TestDuration.Duration, o.startingValue) o.complete() } +// createJobsWithForwarder creates OCR jobs with the forwarder setup. +func (o *OCRSoakTest) createJobsWithForwarder() { + actions.CreateOCRJobsWithForwarder(o.t, o.ocrV1Instances, o.bootstrapNode, o.workerNodes, o.startingValue, o.mockServer, o.sethClient.ChainID) +} + +// createOCRv1Jobs creates OCRv1 jobs. +func (o *OCRSoakTest) createOCRv1Jobs() error { + ctx, cancel := context.WithTimeout(testcontext.Get(o.t), time.Second*5) + defer cancel() + + chainId, err := o.sethClient.Client.ChainID(ctx) + if err != nil { + return fmt.Errorf("error getting chain ID: %w", err) + } + + err = actions.CreateOCRJobs(o.ocrV1Instances, o.bootstrapNode, o.workerNodes, o.startingValue, o.mockServer, chainId.String()) + if err != nil { + return fmt.Errorf("error creating OCRv1 jobs: %w", err) + } + return nil +} + +// createOCRv2Jobs creates OCRv2 jobs. +func (o *OCRSoakTest) createOCRv2Jobs() error { + err := actions.CreateOCRv2Jobs(o.ocrV2Instances, o.bootstrapNode, o.workerNodes, o.mockServer, o.startingValue, o.sethClient.ChainID, o.OperatorForwarderFlow, o.log) + if err != nil { + return fmt.Errorf("error creating OCRv2 jobs: %w", err) + } + return nil +} + // Networks returns the networks that the test is running on func (o *OCRSoakTest) TearDownVals(t *testing.T) ( *testing.T, @@ -418,7 +491,7 @@ func (o *OCRSoakTest) TearDownVals(t *testing.T) ( reportModel.TestReporter, reportModel.GrafanaURLProvider, ) { - return t, o.seth, o.namespace, append(o.workerNodes, o.bootstrapNode), &o.TestReporter, o.Config + return t, o.sethClient, o.namespace, append(o.workerNodes, o.bootstrapNode), &o.TestReporter, o.Config } // ********************* @@ -532,7 +605,7 @@ func (o *OCRSoakTest) LoadState() error { if testState.OCRVersion == "1" { o.ocrV1Instances = make([]contracts.OffchainAggregator, len(testState.OCRContractAddresses)) for i, addr := range testState.OCRContractAddresses { - instance, err := contracts.LoadOffChainAggregator(o.log, o.seth, common.HexToAddress(addr)) + instance, err := contracts.LoadOffChainAggregator(o.log, o.sethClient, common.HexToAddress(addr)) if err != nil { return fmt.Errorf("failed to instantiate OCR instance: %w", err) } @@ -541,7 +614,7 @@ func (o *OCRSoakTest) LoadState() error { } else if testState.OCRVersion == "2" { o.ocrV2Instances = make([]contracts.OffchainAggregatorV2, len(testState.OCRContractAddresses)) for i, addr := range testState.OCRContractAddresses { - instance, err := contracts.LoadOffchainAggregatorV2(o.log, o.seth, common.HexToAddress(addr)) + instance, err := contracts.LoadOffchainAggregatorV2(o.log, o.sethClient, common.HexToAddress(addr)) if err != nil { return err } @@ -780,7 +853,7 @@ func (o *OCRSoakTest) startAnvilGasSpikeSimulation(network blockchain.EVMNetwork func (o *OCRSoakTest) startAnvilGasLimitSimulation(network blockchain.EVMNetwork, conf ctf_config.GasLimitSimulationConfig) { client := ctf_client.NewRPCClient(network.HTTPURLs[0], nil) - latestBlock, err := o.seth.Client.BlockByNumber(context.Background(), nil) + latestBlock, err := o.sethClient.Client.BlockByNumber(context.Background(), nil) require.NoError(o.t, err) newGasLimit := int64(math.Ceil(float64(latestBlock.GasUsed()) * conf.NextGasLimitPercentage)) o.log.Info(). @@ -906,7 +979,7 @@ func (o *OCRSoakTest) pollingOCREvents(ctx context.Context, wg *sync.WaitGroup, // Helper function to poll events and update eventCounter func (o *OCRSoakTest) fetchAndProcessEvents(eventCounter *int, expectedEvents int, processedBlockNum *uint64) { - latestBlock, err := o.seth.Client.BlockNumber(context.Background()) + latestBlock, err := o.sethClient.Client.BlockNumber(context.Background()) if err != nil { o.log.Error().Err(err).Msg("Error getting latest block number") return @@ -939,7 +1012,7 @@ func (o *OCRSoakTest) fetchAndProcessEvents(eventCounter *int, expectedEvents in Uint64("To Block", latestBlock). Msg("Fetching logs for the specified range") - logs, err := o.seth.Client.FilterLogs(context.Background(), o.filterQuery) + logs, err := o.sethClient.Client.FilterLogs(context.Background(), o.filterQuery) if err != nil { o.log.Error().Err(err).Msg("Error fetching logs") return @@ -1056,12 +1129,12 @@ func (o *OCRSoakTest) collectEvents() error { o.log.Info().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Retrieving on-chain events") ctx, cancel := context.WithTimeout(testcontext.Get(o.t), timeout) - contractEvents, err := o.seth.Client.FilterLogs(ctx, o.filterQuery) + contractEvents, err := o.sethClient.Client.FilterLogs(ctx, o.filterQuery) cancel() for err != nil { o.log.Info().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Retrieving on-chain events") ctx, cancel := context.WithTimeout(testcontext.Get(o.t), timeout) - contractEvents, err = o.seth.Client.FilterLogs(ctx, o.filterQuery) + contractEvents, err = o.sethClient.Client.FilterLogs(ctx, o.filterQuery) cancel() if err != nil { o.log.Warn().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Error collecting on-chain events, trying again") diff --git a/integration-tests/utils/pgtest/pgtest.go b/integration-tests/utils/pgtest/pgtest.go new file mode 100644 index 00000000000..8b11f9ef424 --- /dev/null +++ b/integration-tests/utils/pgtest/pgtest.go @@ -0,0 +1,35 @@ +package pgtest + +import ( + "testing" + + "github.com/google/uuid" + "github.com/jmoiron/sqlx" + "github.com/scylladb/go-reflectx" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" +) + +func NewSqlxDB(t testing.TB) *sqlx.DB { + db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), uuid.New().String()) + require.NoError(t, err) + t.Cleanup(func() { assert.NoError(t, db.Close()) }) + db.MapperFunc(reflectx.CamelToSnakeASCII) + + return db +} + +func MustExec(t *testing.T, ds sqlutil.DataSource, stmt string, args ...interface{}) { + ctx := tests.Context(t) + require.NoError(t, utils.JustError(ds.ExecContext(ctx, stmt, args...))) +} + +func MustCount(t *testing.T, db *sqlx.DB, stmt string, args ...interface{}) (cnt int) { + require.NoError(t, db.Get(&cnt, stmt, args...)) + return +} diff --git a/integration-tests/utils/pgtest/txdb.go b/integration-tests/utils/pgtest/txdb.go new file mode 100644 index 00000000000..f28b6f95f2b --- /dev/null +++ b/integration-tests/utils/pgtest/txdb.go @@ -0,0 +1,510 @@ +package pgtest + +import ( + "context" + "database/sql" + "database/sql/driver" + "flag" + "fmt" + "io" + "net/url" + "strings" + "sync" + "testing" + + "github.com/jmoiron/sqlx" + "go.uber.org/multierr" + + "github.com/smartcontractkit/chainlink/v2/core/config/env" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" +) + +// txdb is a simplified version of https://github.com/DATA-DOG/go-txdb +// +// The original lib has various problems and is hard to understand because it +// tries to be more general. The version in this file is more tightly focused +// to our needs and should be easier to reason about and less likely to have +// subtle bugs/races. +// +// It doesn't currently support savepoints but could be made to if necessary. +// +// Transaction BEGIN/ROLLBACK effectively becomes a no-op, this should have no +// negative impact on normal test operation. +// +// If you MUST test BEGIN/ROLLBACK behaviour, you will have to configure your +// store to use the raw DialectPostgres dialect and setup a one-use database. +// See heavyweight.FullTestDB() as a convenience function to help you do this, +// but please use sparingly because as it's name implies, it is expensive. +func init() { + testing.Init() + if !flag.Parsed() { + flag.Parse() + } + if testing.Short() { + // -short tests don't need a DB + return + } + dbURL := string(env.DatabaseURL.Get()) + if dbURL == "" { + panic("you must provide a CL_DATABASE_URL environment variable") + } + + parsed, err := url.Parse(dbURL) + if err != nil { + panic(err) + } + if parsed.Path == "" { + msg := fmt.Sprintf("invalid %[1]s: `%[2]s`. You must set %[1]s env var to point to your test database. Note that the test database MUST end in `_test` to differentiate from a possible production DB. HINT: Try %[1]s=postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable", env.DatabaseURL, parsed.String()) + panic(msg) + } + if !strings.HasSuffix(parsed.Path, "_test") { + msg := fmt.Sprintf("cannot run tests against database named `%s`. Note that the test database MUST end in `_test` to differentiate from a possible production DB. HINT: Try %s=postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable", parsed.Path[1:], env.DatabaseURL) + panic(msg) + } + name := string(dialects.TransactionWrappedPostgres) + sql.Register(name, &txDriver{ + dbURL: dbURL, + conns: make(map[string]*conn), + }) + sqlx.BindDriver(name, sqlx.DOLLAR) +} + +var _ driver.Conn = &conn{} + +var _ driver.Validator = &conn{} +var _ driver.SessionResetter = &conn{} + +// txDriver is an sql driver which runs on a single transaction. +// When `Close` is called, transaction is rolled back. +type txDriver struct { + sync.Mutex + db *sql.DB + conns map[string]*conn + + dbURL string +} + +func (d *txDriver) Open(dsn string) (driver.Conn, error) { + d.Lock() + defer d.Unlock() + // Open real db connection if its the first call + if d.db == nil { + db, err := sql.Open(string(dialects.Postgres), d.dbURL) + if err != nil { + return nil, err + } + d.db = db + } + c, exists := d.conns[dsn] + if !exists || !c.tryOpen() { + tx, err := d.db.Begin() + if err != nil { + return nil, err + } + c = &conn{tx: tx, opened: 1, dsn: dsn} + c.removeSelf = func() error { + return d.deleteConn(c) + } + d.conns[dsn] = c + } + return c, nil +} + +// deleteConn is called by a connection when it is closed via the `close` method. +// It also auto-closes the DB when the last checked out connection is closed. +func (d *txDriver) deleteConn(c *conn) error { + // must lock here to avoid racing with Open + d.Lock() + defer d.Unlock() + + if d.conns[c.dsn] != c { + return nil // already been replaced + } + delete(d.conns, c.dsn) + if len(d.conns) == 0 && d.db != nil { + if err := d.db.Close(); err != nil { + return err + } + d.db = nil + } + return nil +} + +type conn struct { + sync.Mutex + dsn string + tx *sql.Tx // tx may be shared by many conns, definitive one lives in the map keyed by DSN on the txDriver. Do not modify from conn + closed bool + opened int + removeSelf func() error +} + +func (c *conn) Begin() (driver.Tx, error) { + c.Lock() + defer c.Unlock() + if c.closed { + panic("conn is closed") + } + // Begin is a noop because the transaction was already opened + return tx{c.tx}, nil +} + +// Implement the "ConnBeginTx" interface +func (c *conn) BeginTx(_ context.Context, opts driver.TxOptions) (driver.Tx, error) { + // Context is ignored, because single transaction is shared by all callers, thus caller should not be able to + // control it with local context + return c.Begin() +} + +// Prepare returns a prepared statement, bound to this connection. +func (c *conn) Prepare(query string) (driver.Stmt, error) { + return c.PrepareContext(context.Background(), query) +} + +// Implement the "ConnPrepareContext" interface +func (c *conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { + c.Lock() + defer c.Unlock() + if c.closed { + panic("conn is closed") + } + + // TODO: Fix context handling + // FIXME: It is not safe to give the passed in context to the tx directly + // because the tx is shared by many conns and cancelling the context will + // destroy the tx which can affect other conns + st, err := c.tx.PrepareContext(context.Background(), query) + if err != nil { + return nil, err + } + return &stmt{st, c}, nil +} + +// IsValid is called prior to placing the connection into the +// connection pool by database/sql. The connection will be discarded if false is returned. +func (c *conn) IsValid() bool { + c.Lock() + defer c.Unlock() + return !c.closed +} + +func (c *conn) ResetSession(ctx context.Context) error { + // Ensure bad connections are reported: From database/sql/driver: + // If a connection is never returned to the connection pool but immediately reused, then + // ResetSession is called prior to reuse but IsValid is not called. + c.Lock() + defer c.Unlock() + if c.closed { + return driver.ErrBadConn + } + + return nil +} + +// pgx returns nil +func (c *conn) CheckNamedValue(nv *driver.NamedValue) error { + return nil +} + +// Implement the "QueryerContext" interface +func (c *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { + c.Lock() + defer c.Unlock() + if c.closed { + panic("conn is closed") + } + + // TODO: Fix context handling + rs, err := c.tx.QueryContext(context.Background(), query, mapNamedArgs(args)...) + if err != nil { + return nil, err + } + defer rs.Close() + + return buildRows(rs) +} + +// Implement the "ExecerContext" interface +func (c *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { + c.Lock() + defer c.Unlock() + if c.closed { + panic("conn is closed") + } + // TODO: Fix context handling + return c.tx.ExecContext(context.Background(), query, mapNamedArgs(args)...) +} + +// tryOpen attempts to increment the open count, but returns false if closed. +func (c *conn) tryOpen() bool { + c.Lock() + defer c.Unlock() + if c.closed { + return false + } + c.opened++ + return true +} + +// Close invalidates and potentially stops any current +// prepared statements and transactions, marking this +// connection as no longer in use. +// +// Because the sql package maintains a free pool of +// connections and only calls Close when there's a surplus of +// idle connections, it shouldn't be necessary for drivers to +// do their own connection caching. +// +// Drivers must ensure all network calls made by Close +// do not block indefinitely (e.g. apply a timeout). +func (c *conn) Close() (err error) { + if !c.close() { + return + } + // Wait to remove self to avoid nesting locks. + if err := c.removeSelf(); err != nil { + panic(err) + } + return +} + +//nolint:revive +func (c *conn) close() bool { + c.Lock() + defer c.Unlock() + if c.closed { + // Double close, should be a safe to make this a noop + // PGX allows double close + // See: https://github.com/jackc/pgx/blob/a457da8bffa4f90ad672fa093ee87f20cf06687b/conn.go#L249 + return false + } + + c.opened-- + if c.opened > 0 { + return false + } + if c.tx != nil { + if err := c.tx.Rollback(); err != nil { + panic(err) + } + c.tx = nil + } + c.closed = true + return true +} + +type tx struct { + tx *sql.Tx +} + +func (tx tx) Commit() error { + // Commit is a noop because the transaction will be rolled back at the end + return nil +} + +func (tx tx) Rollback() error { + // Rollback is a noop because the transaction will be rolled back at the end + return nil +} + +type stmt struct { + st *sql.Stmt + conn *conn +} + +func (s stmt) Exec(args []driver.Value) (driver.Result, error) { + s.conn.Lock() + defer s.conn.Unlock() + if s.conn.closed { + panic("conn is closed") + } + return s.st.Exec(mapArgs(args)...) +} + +// Implement the "StmtExecContext" interface +func (s *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) { + s.conn.Lock() + defer s.conn.Unlock() + if s.conn.closed { + panic("conn is closed") + } + // TODO: Fix context handling + return s.st.ExecContext(context.Background(), mapNamedArgs(args)...) +} + +func mapArgs(args []driver.Value) (res []interface{}) { + res = make([]interface{}, len(args)) + for i := range args { + res[i] = args[i] + } + return +} + +func (s stmt) NumInput() int { + return -1 +} + +func (s stmt) Query(args []driver.Value) (driver.Rows, error) { + s.conn.Lock() + defer s.conn.Unlock() + if s.conn.closed { + panic("conn is closed") + } + rows, err := s.st.Query(mapArgs(args)...) + defer func() { + err = multierr.Combine(err, rows.Close()) + }() + if err != nil { + return nil, err + } + return buildRows(rows) +} + +// Implement the "StmtQueryContext" interface +func (s *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { + s.conn.Lock() + defer s.conn.Unlock() + if s.conn.closed { + panic("conn is closed") + } + // TODO: Fix context handling + rows, err := s.st.QueryContext(context.Background(), mapNamedArgs(args)...) + if err != nil { + return nil, err + } + return buildRows(rows) +} + +func (s stmt) Close() error { + s.conn.Lock() + defer s.conn.Unlock() + return s.st.Close() +} + +func buildRows(r *sql.Rows) (driver.Rows, error) { + set := &rowSets{} + rs := &rows{} + if err := rs.read(r); err != nil { + return set, err + } + set.sets = append(set.sets, rs) + for r.NextResultSet() { + rss := &rows{} + if err := rss.read(r); err != nil { + return set, err + } + set.sets = append(set.sets, rss) + } + return set, nil +} + +// Implement the "RowsNextResultSet" interface +func (rs *rowSets) HasNextResultSet() bool { + return rs.pos+1 < len(rs.sets) +} + +// Implement the "RowsNextResultSet" interface +func (rs *rowSets) NextResultSet() error { + if !rs.HasNextResultSet() { + return io.EOF + } + + rs.pos++ + return nil +} + +type rows struct { + rows [][]driver.Value + pos int + cols []string + colTypes []*sql.ColumnType +} + +func (r *rows) Columns() []string { + return r.cols +} + +func (r *rows) ColumnTypeDatabaseTypeName(index int) string { + return r.colTypes[index].DatabaseTypeName() +} + +func (r *rows) Next(dest []driver.Value) error { + r.pos++ + if r.pos > len(r.rows) { + return io.EOF + } + + for i, val := range r.rows[r.pos-1] { + dest[i] = *(val.(*interface{})) + } + + return nil +} + +func (r *rows) Close() error { + return nil +} + +func (r *rows) read(rs *sql.Rows) error { + var err error + r.cols, err = rs.Columns() + if err != nil { + return err + } + + r.colTypes, err = rs.ColumnTypes() + if err != nil { + return err + } + + for rs.Next() { + values := make([]interface{}, len(r.cols)) + for i := range values { + values[i] = new(interface{}) + } + if err := rs.Scan(values...); err != nil { + return err + } + row := make([]driver.Value, len(r.cols)) + for i, v := range values { + row[i] = driver.Value(v) + } + r.rows = append(r.rows, row) + } + return rs.Err() +} + +type rowSets struct { + sets []*rows + pos int +} + +func (rs *rowSets) Columns() []string { + return rs.sets[rs.pos].cols +} + +func (rs *rowSets) ColumnTypeDatabaseTypeName(index int) string { + return rs.sets[rs.pos].ColumnTypeDatabaseTypeName(index) +} + +func (rs *rowSets) Close() error { + return nil +} + +// advances to next row +func (rs *rowSets) Next(dest []driver.Value) error { + return rs.sets[rs.pos].Next(dest) +} + +func mapNamedArgs(args []driver.NamedValue) (res []interface{}) { + res = make([]interface{}, len(args)) + for i := range args { + name := args[i].Name + if name != "" { + res[i] = sql.Named(name, args[i].Value) + } else { + res[i] = args[i].Value + } + } + return +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5458e7e0f9f..492624a2a6c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,20 +20,16 @@ importers: packages: - '@babel/code-frame@7.24.7': - resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.24.7': - resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@babel/highlight@7.24.7': - resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} - engines: {node: '>=6.9.0'} - - '@babel/runtime@7.25.6': - resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} + '@babel/runtime@7.26.0': + resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} engines: {node: '>=6.9.0'} '@changesets/apply-release-plan@6.1.4': @@ -297,8 +293,8 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es-abstract@1.23.3: - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + es-abstract@1.23.5: + resolution: {integrity: sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==} engines: {node: '>= 0.4'} es-define-property@1.0.0: @@ -320,8 +316,8 @@ packages: es-shim-unscopables@1.0.2: resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} escalade@3.2.0: @@ -483,6 +479,10 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-async-function@2.0.0: + resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} + engines: {node: '>= 0.4'} + is-bigint@1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} @@ -514,14 +514,26 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + is-finalizationregistry@1.1.0: + resolution: {integrity: sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==} + engines: {node: '>= 0.4'} + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + is-negative-zero@2.0.3: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} @@ -542,6 +554,10 @@ packages: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + is-shared-array-buffer@1.0.3: resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} engines: {node: '>= 0.4'} @@ -562,9 +578,17 @@ packages: resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} engines: {node: '>= 0.4'} + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + is-weakset@2.0.3: + resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} + engines: {node: '>= 0.4'} + is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -661,8 +685,8 @@ packages: normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - object-inspect@1.13.2: - resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + object-inspect@1.13.3: + resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} engines: {node: '>= 0.4'} object-keys@1.1.1: @@ -723,8 +747,8 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - picocolors@1.1.0: - resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -777,11 +801,15 @@ packages: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} + reflect.getprototypeof@1.0.7: + resolution: {integrity: sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==} + engines: {node: '>= 0.4'} + regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + regexp.prototype.flags@1.5.3: + resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==} engines: {node: '>= 0.4'} require-directory@2.1.1: @@ -965,12 +993,12 @@ packages: resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} engines: {node: '>= 0.4'} - typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + typed-array-byte-offset@1.0.3: + resolution: {integrity: sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==} engines: {node: '>= 0.4'} - typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} unbox-primitive@1.0.2: @@ -995,6 +1023,14 @@ packages: which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + which-builtin-type@1.2.0: + resolution: {integrity: sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} @@ -1002,8 +1038,8 @@ packages: resolution: {integrity: sha512-MOiaDbA5ZZgUjkeMWM5EkJp4loW5ZRoa5bc3/aeMox/PJelMhE6t7S/mLuiY43DBupyxH+S0U1bTui9kWUlmsw==} engines: {node: '>=8.15'} - which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + which-typed-array@1.1.16: + resolution: {integrity: sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==} engines: {node: '>= 0.4'} which@1.3.1: @@ -1050,27 +1086,21 @@ packages: snapshots: - '@babel/code-frame@7.24.7': - dependencies: - '@babel/highlight': 7.24.7 - picocolors: 1.1.0 - - '@babel/helper-validator-identifier@7.24.7': {} - - '@babel/highlight@7.24.7': + '@babel/code-frame@7.26.2': dependencies: - '@babel/helper-validator-identifier': 7.24.7 - chalk: 2.4.2 + '@babel/helper-validator-identifier': 7.25.9 js-tokens: 4.0.0 - picocolors: 1.1.0 + picocolors: 1.1.1 - '@babel/runtime@7.25.6': + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/runtime@7.26.0': dependencies: regenerator-runtime: 0.14.1 '@changesets/apply-release-plan@6.1.4': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.0 '@changesets/config': 2.3.1 '@changesets/get-version-range-type': 0.3.2 '@changesets/git': 2.0.0 @@ -1086,7 +1116,7 @@ snapshots: '@changesets/assemble-release-plan@5.2.4': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.0 '@changesets/errors': 0.1.4 '@changesets/get-dependents-graph': 1.3.6 '@changesets/types': 5.2.1 @@ -1099,7 +1129,7 @@ snapshots: '@changesets/cli@2.26.2': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.0 '@changesets/apply-release-plan': 6.1.4 '@changesets/assemble-release-plan': 5.2.4 '@changesets/changelog-git': 0.1.14 @@ -1164,7 +1194,7 @@ snapshots: '@changesets/get-release-plan@3.0.17': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.0 '@changesets/assemble-release-plan': 5.2.4 '@changesets/config': 2.3.1 '@changesets/pre': 1.0.14 @@ -1176,7 +1206,7 @@ snapshots: '@changesets/git@2.0.0': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.0 '@changesets/errors': 0.1.4 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 @@ -1195,7 +1225,7 @@ snapshots: '@changesets/pre@1.0.14': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.0 '@changesets/errors': 0.1.4 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 @@ -1203,7 +1233,7 @@ snapshots: '@changesets/read@0.5.9': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.0 '@changesets/git': 2.0.0 '@changesets/logger': 0.0.5 '@changesets/parse': 0.3.16 @@ -1218,7 +1248,7 @@ snapshots: '@changesets/write@0.2.3': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.0 '@changesets/types': 5.2.1 fs-extra: 7.0.1 human-id: 1.0.2 @@ -1226,14 +1256,14 @@ snapshots: '@manypkg/find-root@1.1.0': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.0 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 '@manypkg/get-packages@1.1.3': dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.26.0 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 @@ -1291,7 +1321,7 @@ snapshots: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.23.3 + es-abstract: 1.23.5 es-shim-unscopables: 1.0.2 arraybuffer.prototype.slice@1.0.3: @@ -1299,7 +1329,7 @@ snapshots: array-buffer-byte-length: 1.0.1 call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.23.3 + es-abstract: 1.23.5 es-errors: 1.3.0 get-intrinsic: 1.2.4 is-array-buffer: 3.0.4 @@ -1459,7 +1489,7 @@ snapshots: dependencies: is-arrayish: 0.2.1 - es-abstract@1.23.3: + es-abstract@1.23.5: dependencies: array-buffer-byte-length: 1.0.1 arraybuffer.prototype.slice: 1.0.3 @@ -1472,7 +1502,7 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.0.0 es-set-tostringtag: 2.0.3 - es-to-primitive: 1.2.1 + es-to-primitive: 1.3.0 function.prototype.name: 1.1.6 get-intrinsic: 1.2.4 get-symbol-description: 1.0.2 @@ -1492,10 +1522,10 @@ snapshots: is-string: 1.0.7 is-typed-array: 1.1.13 is-weakref: 1.0.2 - object-inspect: 1.13.2 + object-inspect: 1.13.3 object-keys: 1.1.1 object.assign: 4.1.5 - regexp.prototype.flags: 1.5.2 + regexp.prototype.flags: 1.5.3 safe-array-concat: 1.1.2 safe-regex-test: 1.0.3 string.prototype.trim: 1.2.9 @@ -1503,10 +1533,10 @@ snapshots: string.prototype.trimstart: 1.0.8 typed-array-buffer: 1.0.2 typed-array-byte-length: 1.0.1 - typed-array-byte-offset: 1.0.2 - typed-array-length: 1.0.6 + typed-array-byte-offset: 1.0.3 + typed-array-length: 1.0.7 unbox-primitive: 1.0.2 - which-typed-array: 1.1.15 + which-typed-array: 1.1.16 es-define-property@1.0.0: dependencies: @@ -1528,7 +1558,7 @@ snapshots: dependencies: hasown: 2.0.2 - es-to-primitive@1.2.1: + es-to-primitive@1.3.0: dependencies: is-callable: 1.2.7 is-date-object: 1.0.5 @@ -1601,7 +1631,7 @@ snapshots: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.23.3 + es-abstract: 1.23.5 functions-have-names: 1.2.3 functions-have-names@1.2.3: {} @@ -1697,6 +1727,10 @@ snapshots: is-arrayish@0.2.1: {} + is-async-function@2.0.0: + dependencies: + has-tostringtag: 1.0.2 + is-bigint@1.0.4: dependencies: has-bigints: 1.0.2 @@ -1726,12 +1760,22 @@ snapshots: is-extglob@2.1.1: {} + is-finalizationregistry@1.1.0: + dependencies: + call-bind: 1.0.7 + is-fullwidth-code-point@3.0.0: {} + is-generator-function@1.0.10: + dependencies: + has-tostringtag: 1.0.2 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 + is-map@2.0.3: {} + is-negative-zero@2.0.3: {} is-number-object@1.0.7: @@ -1747,6 +1791,8 @@ snapshots: call-bind: 1.0.7 has-tostringtag: 1.0.2 + is-set@2.0.3: {} + is-shared-array-buffer@1.0.3: dependencies: call-bind: 1.0.7 @@ -1765,12 +1811,19 @@ snapshots: is-typed-array@1.1.13: dependencies: - which-typed-array: 1.1.15 + which-typed-array: 1.1.16 + + is-weakmap@2.0.2: {} is-weakref@1.0.2: dependencies: call-bind: 1.0.7 + is-weakset@2.0.3: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + is-windows@1.0.2: {} isarray@2.0.5: {} @@ -1864,7 +1917,7 @@ snapshots: semver: 5.7.2 validate-npm-package-license: 3.0.4 - object-inspect@1.13.2: {} + object-inspect@1.13.3: {} object-keys@1.1.1: {} @@ -1905,7 +1958,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.24.7 + '@babel/code-frame': 7.26.2 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -1916,7 +1969,7 @@ snapshots: path-type@4.0.0: {} - picocolors@1.1.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -1968,9 +2021,19 @@ snapshots: indent-string: 4.0.0 strip-indent: 3.0.0 + reflect.getprototypeof@1.0.7: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.5 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + which-builtin-type: 1.2.0 + regenerator-runtime@0.14.1: {} - regexp.prototype.flags@1.5.2: + regexp.prototype.flags@1.5.3: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 @@ -2043,7 +2106,7 @@ snapshots: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 - object-inspect: 1.13.2 + object-inspect: 1.13.3 signal-exit@3.0.7: {} @@ -2093,7 +2156,7 @@ snapshots: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.23.3 + es-abstract: 1.23.5 es-object-atoms: 1.0.0 string.prototype.trimend@1.0.8: @@ -2172,7 +2235,7 @@ snapshots: has-proto: 1.0.3 is-typed-array: 1.1.13 - typed-array-byte-offset@1.0.2: + typed-array-byte-offset@1.0.3: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 @@ -2180,15 +2243,16 @@ snapshots: gopd: 1.0.1 has-proto: 1.0.3 is-typed-array: 1.1.13 + reflect.getprototypeof: 1.0.7 - typed-array-length@1.0.6: + typed-array-length@1.0.7: dependencies: call-bind: 1.0.7 for-each: 0.3.3 gopd: 1.0.1 - has-proto: 1.0.3 is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 + reflect.getprototypeof: 1.0.7 unbox-primitive@1.0.2: dependencies: @@ -2223,6 +2287,29 @@ snapshots: is-string: 1.0.7 is-symbol: 1.0.4 + which-builtin-type@1.2.0: + dependencies: + call-bind: 1.0.7 + function.prototype.name: 1.1.6 + has-tostringtag: 1.0.2 + is-async-function: 2.0.0 + is-date-object: 1.0.5 + is-finalizationregistry: 1.1.0 + is-generator-function: 1.0.10 + is-regex: 1.1.4 + is-weakref: 1.0.2 + isarray: 2.0.5 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.2 + which-typed-array: 1.1.16 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.3 + which-module@2.0.1: {} which-pm@2.2.0: @@ -2230,7 +2317,7 @@ snapshots: load-yaml-file: 0.2.0 path-exists: 4.0.0 - which-typed-array@1.1.15: + which-typed-array@1.1.16: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 diff --git a/shell.nix b/shell.nix index 8d5b4351b25..4065e7e3def 100644 --- a/shell.nix +++ b/shell.nix @@ -1,6 +1,6 @@ {pkgs, isCrib}: with pkgs; let - go = go_1_21; + go = go_1_23; postgresql = postgresql_15; nodejs = nodejs-18_x; nodePackages = pkgs.nodePackages.override {inherit nodejs;}; diff --git a/tools/bin/go_core_ccip_deployment_tests b/tools/bin/go_core_ccip_deployment_tests index de976741398..2a598c55cbd 100755 --- a/tools/bin/go_core_ccip_deployment_tests +++ b/tools/bin/go_core_ccip_deployment_tests @@ -14,7 +14,7 @@ echo "" if [[ $GITHUB_EVENT_NAME == "schedule" ]]; then EXTRA_FLAGS="-covermode=atomic -coverpkg=./... -coverprofile=coverage.txt" fi -go test ./... "$EXTRA_FLAGS" | tee $OUTPUT_FILE | grep -Ev '\[no test files\]|\[no tests to run\]' +go test ./... $EXTRA_FLAGS | tee $OUTPUT_FILE | grep -Ev '\[no test files\]|\[no tests to run\]' EXITCODE=${PIPESTATUS[0]} # Assert no known sensitive strings present in test logger output diff --git a/tools/bin/go_core_tests b/tools/bin/go_core_tests index 0fffcb72a39..76c15fccd07 100755 --- a/tools/bin/go_core_tests +++ b/tools/bin/go_core_tests @@ -4,14 +4,14 @@ set +e SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"` OUTPUT_FILE=${OUTPUT_FILE:-"./output.txt"} -EXTRA_FLAGS="" +EXTRA_FLAGS="-timeout 20m" echo "Test execution results: ---------------------" echo "" if [[ $GITHUB_EVENT_NAME == "schedule" ]]; then EXTRA_FLAGS="-covermode=atomic -coverpkg=./... -coverprofile=coverage.txt" fi -go test "$EXTRA_FLAGS" $1 | tee $OUTPUT_FILE | grep -Ev '\[no test files\]|\[no tests to run\]' +go test $EXTRA_FLAGS $1 | tee $OUTPUT_FILE | grep -Ev '\[no test files\]|\[no tests to run\]' EXITCODE=${PIPESTATUS[0]} # Assert no known sensitive strings present in test logger output diff --git a/tools/bin/go_core_tests_integration b/tools/bin/go_core_tests_integration index 323e9d526ac..70a9118d286 100755 --- a/tools/bin/go_core_tests_integration +++ b/tools/bin/go_core_tests_integration @@ -23,7 +23,7 @@ if [[ $GITHUB_EVENT_NAME == "schedule" ]]; then # COVERPKG_DIRS=$(echo "$INTEGRATION_TEST_DIRS $ALL_IMPORTS" | grep "smartcontractkit/chainlink" | tr '\n' ',') EXTRA_FLAGS="-covermode=atomic -coverpkg=./... -coverprofile=coverage.txt" fi -go test -tags integration "$EXTRA_FLAGS" $INTEGRATION_TEST_DIRS_SPACE_DELIMITED | tee $OUTPUT_FILE | grep -Ev '\[no test files\]|\[no tests to run\]' +go test -tags integration $EXTRA_FLAGS $INTEGRATION_TEST_DIRS_SPACE_DELIMITED | tee $OUTPUT_FILE | grep -Ev '\[no test files\]|\[no tests to run\]' EXITCODE=${PIPESTATUS[0]} # Assert no known sensitive strings present in test logger output